befly 3.15.19 → 3.15.20

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
@@ -10227,6 +10227,8 @@ class SyncTable {
10227
10227
  throw new Error("\u540C\u6B65\u8868\uFF1A\u8BF7\u4F20\u5165\u591A\u4E2A\u8868\u5B9A\u4E49\u7EC4\u6210\u7684\u6570\u7EC4");
10228
10228
  }
10229
10229
  await SyncTable.ensureDbVersion(this.db);
10230
+ const tableTasks = [];
10231
+ const incompatibleTypeChanges = [];
10230
10232
  for (const item of items) {
10231
10233
  if (!item || item.type !== "table") {
10232
10234
  continue;
@@ -10237,9 +10239,98 @@ class SyncTable {
10237
10239
  SyncTable.normalizeFieldDefinitionInPlace(fieldDef);
10238
10240
  }
10239
10241
  const existsTable = await SyncTable.tableExists(this.db, this.dbName, tableName);
10242
+ const task = {
10243
+ item,
10244
+ tableName,
10245
+ tableFields,
10246
+ existsTable,
10247
+ existingColumns: null,
10248
+ existingIndexes: null,
10249
+ plan: null,
10250
+ planSummary: null,
10251
+ planDetails: null
10252
+ };
10253
+ if (existsTable) {
10254
+ const existingColumns = await SyncTable.getTableColumns(this.db, this.dbName, tableName);
10255
+ const existingIndexes = await SyncTable.getTableIndexes(this.db, this.dbName, tableName);
10256
+ const changes = SyncTable.collectIncompatibleTypeChanges(tableName, existingColumns, tableFields);
10257
+ for (const change of changes) {
10258
+ incompatibleTypeChanges.push(change);
10259
+ }
10260
+ task.existingColumns = existingColumns;
10261
+ task.existingIndexes = existingIndexes;
10262
+ }
10263
+ tableTasks.push(task);
10264
+ }
10265
+ if (incompatibleTypeChanges.length > 0) {
10266
+ const lines = [];
10267
+ for (const change of incompatibleTypeChanges) {
10268
+ lines.push(`- ${change.tableName}.${change.dbFieldName}: ${change.currentType} -> ${change.expectedType}`);
10269
+ }
10270
+ const msgLines = [];
10271
+ msgLines.push("\u7981\u6B62\u5B57\u6BB5\u7C7B\u578B\u53D8\u66F4\uFF08\u68C0\u6D4B\u5230\u4E0D\u517C\u5BB9/\u6536\u7F29\u53D8\u66F4\uFF09:");
10272
+ for (const line of lines) {
10273
+ msgLines.push(line);
10274
+ }
10275
+ msgLines.push("\u8BF4\u660E: \u4EC5\u5141\u8BB8\u540C\u7C7B\u578B\u7684\u5BBD\u5316\u53D8\u66F4\uFF08\u5982 TINYINT->SMALLINT->INT->BIGINT\uFF09\uFF0C\u4EE5\u53CA\u90E8\u5206\u517C\u5BB9\u53D8\u66F4\uFF08\u5982 VARCHAR->TEXT\u3001CHAR/VARCHAR \u4E92\u8F6C\u3001float->double\uFF09\u3002");
10276
+ msgLines.push("\u63D0\u793A: \u82E5\u786E\u9700\u6536\u7F29\uFF0C\u8BF7\u5148\u624B\u5DE5\u8FC1\u79FB/\u6E05\u6D17\u6570\u636E\u540E\u518D\u6267\u884C\u540C\u6B65\u3002");
10277
+ throw new Error(msgLines.join(`
10278
+ `));
10279
+ }
10280
+ for (const task of tableTasks) {
10281
+ if (!task.existsTable) {
10282
+ continue;
10283
+ }
10284
+ if (!task.existingColumns || !task.existingIndexes) {
10285
+ throw new Error(`\u540C\u6B65\u8868\uFF1A\u5185\u90E8\u9519\u8BEF\uFF1A\u9884\u68C0\u9636\u6BB5\u7F3A\u5931\u8868\u5143\u4FE1\u606F\uFF08\u8868=${task.tableName}\uFF09`);
10286
+ }
10287
+ const built = SyncTable.buildTablePlan({
10288
+ tableName: task.tableName,
10289
+ fields: task.tableFields,
10290
+ existingColumns: task.existingColumns,
10291
+ existingIndexes: task.existingIndexes
10292
+ });
10293
+ task.plan = built.plan;
10294
+ task.planSummary = built.summary;
10295
+ task.planDetails = built.details;
10296
+ }
10297
+ for (const task of tableTasks) {
10298
+ const item = task.item;
10299
+ const tableName = task.tableName;
10300
+ const tableFields = task.tableFields;
10301
+ const existsTable = task.existsTable;
10240
10302
  try {
10241
10303
  if (existsTable) {
10242
- await SyncTable.modifyTable(this.db, this.dbName, tableName, tableFields);
10304
+ const plan = task.plan;
10305
+ const summary = task.planSummary;
10306
+ const details = task.planDetails;
10307
+ if (plan && plan.changed && summary && details) {
10308
+ 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}`;
10309
+ const detailLines = details.fieldChanges.flatMap((d) => d.changes.map((change) => {
10310
+ const current = String(change.current ?? "");
10311
+ const expected = String(change.expected ?? "");
10312
+ return `- ${d.dbFieldName}.${change.type}: ${current} -> ${expected}`;
10313
+ }));
10314
+ const indexLines = details.indexChanges.map((change) => {
10315
+ const indexLabel = `idx_${change.fieldName}` === change.indexName ? change.indexName : change.indexName;
10316
+ if (change.action === "create") {
10317
+ return `- index.${indexLabel}: \u65E0 -> ${change.indexName}(${change.fieldName})`;
10318
+ }
10319
+ return `- index.${indexLabel}: ${change.indexName}(${change.fieldName}) -> \u65E0`;
10320
+ });
10321
+ const allLines = [];
10322
+ for (const line of detailLines) {
10323
+ allLines.push(line);
10324
+ }
10325
+ for (const line of indexLines) {
10326
+ allLines.push(line);
10327
+ }
10328
+ Logger.debug(msg);
10329
+ for (const line of allLines) {
10330
+ Logger.debug(`[\u8868 ${tableName}] \u53D8\u66F4\u660E\u7EC6 ${line}`);
10331
+ }
10332
+ await SyncTable.applyTablePlan(this.db, tableName, plan);
10333
+ }
10243
10334
  } else {
10244
10335
  await SyncTable.createTable(this.db, tableName, tableFields);
10245
10336
  }
@@ -10594,6 +10685,32 @@ class SyncTable {
10594
10685
  throw new Error([`\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\uFF1BDATETIME \u4E0E BIGINT \u4E0D\u5141\u8BB8\u4E92\u8F6C\uFF08\u9700\u8981\u624B\u52A8\u8FC1\u79FB\u6570\u636E\uFF09"].join(`
10595
10686
  `));
10596
10687
  }
10688
+ static collectIncompatibleTypeChanges(tableName, existingColumns, fields) {
10689
+ const out = [];
10690
+ for (const [fieldKey, fieldDef] of Object.entries(fields)) {
10691
+ const dbFieldName = snakeCase(fieldKey);
10692
+ const existing = existingColumns[dbFieldName];
10693
+ if (!existing)
10694
+ continue;
10695
+ const comparison = SyncTable.compareFieldDefinition(existing, fieldDef);
10696
+ const typeChange = comparison.find((c) => c.type === "datatype");
10697
+ if (!typeChange)
10698
+ continue;
10699
+ const currentType = String(typeChange.current || "").toLowerCase();
10700
+ const expectedType = String(typeChange.expected || "").toLowerCase();
10701
+ const currentBase = currentType.replace(/\s*unsigned/gi, "").replace(/\([^)]*\)/g, "").trim();
10702
+ const expectedBase = expectedType.replace(/\s*unsigned/gi, "").replace(/\([^)]*\)/g, "").trim();
10703
+ if (currentBase !== expectedBase && !SyncTable.isCompatibleTypeChange(currentType, expectedType)) {
10704
+ out.push({
10705
+ tableName,
10706
+ dbFieldName,
10707
+ currentType: String(typeChange.current ?? ""),
10708
+ expectedType: String(typeChange.expected ?? "")
10709
+ });
10710
+ }
10711
+ }
10712
+ return out;
10713
+ }
10597
10714
  static truncateForLog(input, maxLen) {
10598
10715
  const s = String(input);
10599
10716
  if (maxLen <= 0)