@happyvertical/smrt-cli 0.43.0 → 0.43.2

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.
@@ -493,6 +493,10 @@ function getSyntheticMigrationNameForAction(action) {
493
493
  const fingerprint = sqlShapeFingerprint(action);
494
494
  return fingerprint ? `add_foreign_key_${action.tableName}_${fingerprint}` : null;
495
495
  }
496
+ case "drop_foreign_key": {
497
+ const fingerprint = sqlShapeFingerprint(action);
498
+ return fingerprint ? `drop_foreign_key_${action.tableName}_${fingerprint}` : null;
499
+ }
496
500
  case "drop_index": {
497
501
  if (!action.indexName) return null;
498
502
  const fingerprint = sqlShapeFingerprint(action);
@@ -525,6 +529,10 @@ function getSyntheticMigrationNameForChange(change) {
525
529
  const fingerprint = sqlShapeFingerprint(change);
526
530
  return fingerprint ? `add_foreign_key_${change.table}_${fingerprint}` : null;
527
531
  }
532
+ case "drop_foreign_key": {
533
+ const fingerprint = sqlShapeFingerprint(change);
534
+ return fingerprint ? `drop_foreign_key_${change.table}_${fingerprint}` : null;
535
+ }
528
536
  case "drop_index": {
529
537
  if (!change.name) return null;
530
538
  const fingerprint = sqlShapeFingerprint({
@@ -565,13 +573,13 @@ function shouldApplySchemaMigrations(state) {
565
573
  return !state.dryRun;
566
574
  }
567
575
  function classifyFailedMigration(migrationName, unresolvedSyntheticMigrationNames) {
568
- if (!migrationName.startsWith("add_column_") && !migrationName.startsWith("drop_column_") && !migrationName.startsWith("alter_column_") && !migrationName.startsWith("add_foreign_key_") && !migrationName.startsWith("add_index_") && !migrationName.startsWith("drop_index_") && !migrationName.startsWith("type_upgrade_")) return "other";
576
+ if (!migrationName.startsWith("add_column_") && !migrationName.startsWith("drop_column_") && !migrationName.startsWith("alter_column_") && !migrationName.startsWith("add_foreign_key_") && !migrationName.startsWith("drop_foreign_key_") && !migrationName.startsWith("add_index_") && !migrationName.startsWith("drop_index_") && !migrationName.startsWith("type_upgrade_")) return "other";
569
577
  return unresolvedSyntheticMigrationNames.has(migrationName) ? "unresolved" : "superseded";
570
578
  }
571
579
  function getUnresolvedGeneratedMigrationNames(changes) {
572
580
  const names = /* @__PURE__ */ new Set();
573
581
  for (const change of changes) {
574
- if (change.type !== "add_column" && change.type !== "drop_column" && change.type !== "alter_column" && change.type !== "add_foreign_key" && change.type !== "add_index" && change.type !== "drop_index" && change.type !== "type_upgrade") continue;
582
+ if (change.type !== "add_column" && change.type !== "drop_column" && change.type !== "alter_column" && change.type !== "add_foreign_key" && change.type !== "drop_foreign_key" && change.type !== "add_index" && change.type !== "drop_index" && change.type !== "type_upgrade") continue;
575
583
  if (change.type === "type_upgrade" && classifyTypeUpgradeSql(change.sql) === "noop") continue;
576
584
  if (change.type === "alter_column" && isAdvisoryOnlyChangeLike(change)) continue;
577
585
  for (const migrationName of getSyntheticMigrationNamesForChange(change)) names.add(migrationName);
@@ -714,9 +722,10 @@ function partitionSchemaChanges(changes, getClassForTable) {
714
722
  });
715
723
  break;
716
724
  }
717
- case "add_foreign_key": {
725
+ case "add_foreign_key":
726
+ case "drop_foreign_key": {
718
727
  const action = {
719
- type: "add_foreign_key",
728
+ type: change.type,
720
729
  tableName: change.table,
721
730
  className,
722
731
  sql: change.sql,
@@ -986,7 +995,8 @@ var dbDiffCommand = {
986
995
  }, null, 2));
987
996
  return;
988
997
  }
989
- const { advisories } = partitionSchemaChanges(diff.changes, (tableName) => tableName);
998
+ const { advisories, manualInterventions } = partitionSchemaChanges(diff.changes, (tableName) => tableName);
999
+ const manualForeignKeyChanges = manualInterventions.filter((change) => change.type === "add_foreign_key" || change.type === "drop_foreign_key");
990
1000
  if (!diff.has_changes) {
991
1001
  console.log("✅ Database schema is up to date - no changes detected\n");
992
1002
  printSchemaAdvisories(advisories, {
@@ -995,7 +1005,7 @@ var dbDiffCommand = {
995
1005
  });
996
1006
  return;
997
1007
  }
998
- if (diff.changes.filter((c) => !(c.advisory && !c.sql && !c.sqlStatements)).length === 0 && diff.added_tables.length === 0 && diff.dropped_tables.length === 0) {
1008
+ if (diff.changes.filter((c) => !(c.advisory && !c.sql && !c.sqlStatements)).length === 0 && manualForeignKeyChanges.length === 0 && diff.added_tables.length === 0 && diff.dropped_tables.length === 0) {
999
1009
  console.log("✅ Database schema is up to date - no migrations needed (see notes below)\n");
1000
1010
  printSchemaAdvisories(advisories, {
1001
1011
  orphanTables: diff.orphan_tables,
@@ -1076,6 +1086,16 @@ var dbDiffCommand = {
1076
1086
  for (const change of typeMismatches) console.log(` ! ${change.table}.${change.name}: ${change.mismatch?.expected} vs ${change.mismatch?.actual}`);
1077
1087
  console.log(" (Type changes require manual migration)\n");
1078
1088
  }
1089
+ if (manualForeignKeyChanges.length > 0) {
1090
+ console.log(` ⚠️ Foreign-key drift needing a manual step (${manualForeignKeyChanges.length}):`);
1091
+ for (const change of manualForeignKeyChanges) {
1092
+ const operation = change.type === "drop_foreign_key" ? "remove" : "add";
1093
+ console.log(` ! ${change.tableName}: ${operation} constraint`);
1094
+ console.log(` ${change.advisory?.message ?? "foreign-key constraint requires manual repair"}`);
1095
+ for (const sql of change.advisory?.suggestedSql ?? []) console.log(` ↳ ${sql}`);
1096
+ }
1097
+ console.log();
1098
+ }
1079
1099
  printSchemaAdvisories(advisories, {
1080
1100
  orphanTables: diff.orphan_tables,
1081
1101
  verbose: options.verbose
@@ -2382,6 +2402,17 @@ function summarizeSchemaDiff(diff) {
2382
2402
  recommendation: "Run `smrt db:migrate` to add the missing index and reconcile the live schema."
2383
2403
  });
2384
2404
  break;
2405
+ case "add_foreign_key":
2406
+ case "drop_foreign_key": {
2407
+ const relationship = change.foreignKey ? `${change.table}.${change.foreignKey.column} -> ${change.foreignKey.referencesTable}.${change.foreignKey.referencesColumn}` : `${change.table}.${change.name ?? "(unknown)"}`;
2408
+ const isAddition = change.type === "add_foreign_key";
2409
+ drift.push({
2410
+ name: relationship,
2411
+ type: isAddition ? "missing_foreign_key" : "disabled_foreign_key",
2412
+ recommendation: change.advisory?.message ?? (isAddition ? "Run `smrt db:migrate` to add the missing foreign key and reconcile the live schema." : "Run `smrt db:migrate` to remove the disabled foreign key and reconcile the live schema.")
2413
+ });
2414
+ break;
2415
+ }
2385
2416
  case "type_upgrade":
2386
2417
  switch (classifyTypeUpgradeSql(change.sql)) {
2387
2418
  case "executable":
@@ -8312,7 +8343,7 @@ export default testManifest;
8312
8343
  if (manualInterventions.length > 0) {
8313
8344
  console.log("⚠️ Schema drift detected that requires manual intervention:\n");
8314
8345
  for (const change of manualInterventions) {
8315
- if (change.type === "add_foreign_key") {
8346
+ if (change.type === "add_foreign_key" || change.type === "drop_foreign_key") {
8316
8347
  console.log(` ${change.tableName}: ${change.advisory?.message ?? change.sql?.replace(/^--\s*/, "") ?? "foreign-key constraint requires manual repair"}`);
8317
8348
  for (const sql of change.advisory?.suggestedSql ?? []) console.log(` ${sql}`);
8318
8349
  continue;
@@ -8347,6 +8378,7 @@ export default testManifest;
8347
8378
  const columnMigrations = migrations.filter((m) => m.type === "add_column");
8348
8379
  const indexMigrations = migrations.filter((m) => m.type === "add_index");
8349
8380
  const foreignKeyMigrations = migrations.filter((m) => m.type === "add_foreign_key");
8381
+ const foreignKeyDrops = migrations.filter((m) => m.type === "drop_foreign_key");
8350
8382
  const indexDrops = migrations.filter((m) => m.type === "drop_index");
8351
8383
  const columnAlterations = migrations.filter((m) => m.type === "alter_column");
8352
8384
  const columnDrops = migrations.filter((m) => m.type === "drop_column");
@@ -8380,6 +8412,11 @@ export default testManifest;
8380
8412
  for (const m of foreignKeyMigrations) console.log(` ${m.tableName}`);
8381
8413
  console.log();
8382
8414
  }
8415
+ if (foreignKeyDrops.length > 0) {
8416
+ console.log(` 🔗 Foreign-key constraints to drop: ${foreignKeyDrops.length}`);
8417
+ for (const m of foreignKeyDrops) console.log(` ${m.tableName}`);
8418
+ console.log();
8419
+ }
8383
8420
  console.log(" SQL Statements:\n");
8384
8421
  for (const schema of tablePlan.schemas) {
8385
8422
  const ddl = plannedTableDDL.get(schema.tableName);
@@ -8473,11 +8510,14 @@ export default testManifest;
8473
8510
  } else if (migration.type === "add_foreign_key") {
8474
8511
  migrationSql = migration.sql || "";
8475
8512
  actionDesc = `Added foreign-key constraint on ${migration.tableName}`;
8513
+ } else if (migration.type === "drop_foreign_key") {
8514
+ migrationSql = migration.sql || "";
8515
+ actionDesc = `Dropped foreign-key constraint on ${migration.tableName}`;
8476
8516
  } else continue;
8477
8517
  const migrationSqlStatements = migration.sqlStatements ?? (migrationSql ? [migrationSql] : []);
8478
8518
  migrationDefs.push({
8479
8519
  id: migrationName,
8480
- description: migration.type === "add_column" ? `Add column ${migration.column?.name} to ${migration.tableName}` : migration.type === "alter_column" ? `Alter column ${migration.columnName ?? migration.column?.name} on ${migration.tableName} (${migration.alteration ?? "alter"}: ${migration.mismatch?.actual ?? "?"} → ${migration.mismatch?.expected ?? "?"})` : migration.type === "drop_column" ? `Drop column ${migration.columnName} from ${migration.tableName}` : migration.type === "type_upgrade" ? `Upgrade column ${migration.column?.name} on ${migration.tableName} from ${migration.mismatch?.actual} to ${migration.mismatch?.expected}` : migration.type === "drop_index" ? `Drop index ${migration.indexName} on ${migration.tableName}` : migration.type === "add_foreign_key" ? `Add foreign-key constraint on ${migration.tableName}` : `Add index ${migration.index?.name} on ${migration.tableName}`,
8520
+ description: migration.type === "add_column" ? `Add column ${migration.column?.name} to ${migration.tableName}` : migration.type === "alter_column" ? `Alter column ${migration.columnName ?? migration.column?.name} on ${migration.tableName} (${migration.alteration ?? "alter"}: ${migration.mismatch?.actual ?? "?"} → ${migration.mismatch?.expected ?? "?"})` : migration.type === "drop_column" ? `Drop column ${migration.columnName} from ${migration.tableName}` : migration.type === "type_upgrade" ? `Upgrade column ${migration.column?.name} on ${migration.tableName} from ${migration.mismatch?.actual} to ${migration.mismatch?.expected}` : migration.type === "drop_index" ? `Drop index ${migration.indexName} on ${migration.tableName}` : migration.type === "add_foreign_key" ? `Add foreign-key constraint on ${migration.tableName}` : migration.type === "drop_foreign_key" ? `Drop foreign-key constraint on ${migration.tableName}` : `Add index ${migration.index?.name} on ${migration.tableName}`,
8481
8521
  version: "1.0.0",
8482
8522
  up: migrationSqlStatements,
8483
8523
  down: []
package/dist/index.js CHANGED
@@ -49,63 +49,63 @@ var _playgroundCommands = null;
49
49
  var _workbenchCommands = null;
50
50
  async function getGnodeCommands() {
51
51
  if (!_gnodeCommands) {
52
- const { gnodeCommands } = await import("./commands-C1bK8bv9.js");
52
+ const { gnodeCommands } = await import("./commands-BAKZil1v.js");
53
53
  _gnodeCommands = gnodeCommands;
54
54
  }
55
55
  return _gnodeCommands;
56
56
  }
57
57
  async function getGitCommands() {
58
58
  if (!_gitCommands) {
59
- const { gitCommands } = await import("./commands-C1bK8bv9.js");
59
+ const { gitCommands } = await import("./commands-BAKZil1v.js");
60
60
  _gitCommands = gitCommands;
61
61
  }
62
62
  return _gitCommands;
63
63
  }
64
64
  async function getGenerateCommands() {
65
65
  if (!_generateCommands) {
66
- const { generateCommands } = await import("./commands-C1bK8bv9.js");
66
+ const { generateCommands } = await import("./commands-BAKZil1v.js");
67
67
  _generateCommands = generateCommands;
68
68
  }
69
69
  return _generateCommands;
70
70
  }
71
71
  async function getInitCommands() {
72
72
  if (!_initCommands) {
73
- const { initCommands } = await import("./commands-C1bK8bv9.js");
73
+ const { initCommands } = await import("./commands-BAKZil1v.js");
74
74
  _initCommands = initCommands;
75
75
  }
76
76
  return _initCommands;
77
77
  }
78
78
  async function getUtilityCommands() {
79
79
  if (!_utilityCommands) {
80
- const { utilityCommands } = await import("./commands-C1bK8bv9.js");
80
+ const { utilityCommands } = await import("./commands-BAKZil1v.js");
81
81
  _utilityCommands = utilityCommands;
82
82
  }
83
83
  return _utilityCommands;
84
84
  }
85
85
  async function getDispatchCommands() {
86
86
  if (!_dispatchCommands) {
87
- const { dispatchCommands } = await import("./commands-C1bK8bv9.js");
87
+ const { dispatchCommands } = await import("./commands-BAKZil1v.js");
88
88
  _dispatchCommands = dispatchCommands;
89
89
  }
90
90
  return _dispatchCommands;
91
91
  }
92
92
  async function getDocsCommands() {
93
93
  if (!_docsCommands) {
94
- const { docsCommands } = await import("./commands-C1bK8bv9.js");
94
+ const { docsCommands } = await import("./commands-BAKZil1v.js");
95
95
  _docsCommands = docsCommands;
96
96
  }
97
97
  return _docsCommands;
98
98
  }
99
99
  async function getPlaygroundCommands() {
100
100
  if (!_playgroundCommands) {
101
- const { playgroundCommands } = await import("./commands-C1bK8bv9.js");
101
+ const { playgroundCommands } = await import("./commands-BAKZil1v.js");
102
102
  _playgroundCommands = playgroundCommands;
103
103
  }
104
104
  return _playgroundCommands;
105
105
  }
106
106
  async function getWorkbenchCommands() {
107
107
  if (!_workbenchCommands) {
108
- const { workbenchCommands } = await import("./commands-C1bK8bv9.js");
108
+ const { workbenchCommands } = await import("./commands-BAKZil1v.js");
109
109
  _workbenchCommands = workbenchCommands;
110
110
  }
111
111
  return _workbenchCommands;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-cli",
3
- "version": "0.43.0",
3
+ "version": "0.43.2",
4
4
  "description": "Developer CLI for SMRT framework - introspection, testing, and project management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -32,12 +32,12 @@
32
32
  "acorn": "^8.17.0",
33
33
  "fast-glob": "3.3.3",
34
34
  "tar": "^7.5.19",
35
- "@happyvertical/smrt-agents": "0.43.0",
36
- "@happyvertical/smrt-config": "0.43.0",
37
- "@happyvertical/smrt-core": "0.43.0",
38
- "@happyvertical/smrt-playground": "0.43.0",
39
- "@happyvertical/smrt-types": "0.43.0",
40
- "@happyvertical/smrt-dev-mcp": "0.43.0"
35
+ "@happyvertical/smrt-agents": "0.43.2",
36
+ "@happyvertical/smrt-core": "0.43.2",
37
+ "@happyvertical/smrt-config": "0.43.2",
38
+ "@happyvertical/smrt-dev-mcp": "0.43.2",
39
+ "@happyvertical/smrt-playground": "0.43.2",
40
+ "@happyvertical/smrt-types": "0.43.2"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "24.13.2",