@happyvertical/smrt-cli 0.40.30 → 0.40.32

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/README.md CHANGED
@@ -67,14 +67,17 @@ smrt db:migrate --postgres-timestamp-legacy-timezone UTC
67
67
  ```
68
68
 
69
69
  The option has no default and rejects every value other than `UTC`. On
70
- PostgreSQL, it allows the manifest-owned timestamp columns to be converted to
71
- `timestamptz` with `USING column AT TIME ZONE 'UTC'`, preserving the proven UTC
72
- instants. It is not safe for a database with any local-time writer; use an
73
- application-owned, provenance-aware migration in that case. Rehearse against a
74
- restored clone and keep a verified backup because type upgrades have no
75
- automatic down migration. `smrt db:diff --postgres-timestamp-legacy-timezone
76
- UTC` and `smrt db:migrate --dry-run --postgres-timestamp-legacy-timezone UTC`
77
- both preview the same conversion without writing it.
70
+ PostgreSQL, `db:migrate` first converts framework-owned `_smrt_*` timestamp
71
+ columns before migration-tracker bootstrap, then converts manifest-owned
72
+ columns to `timestamptz` with `USING column AT TIME ZONE 'UTC'`. This preserves
73
+ the proven UTC instants. It is not safe for a database with any local-time
74
+ writer; use an application-owned, provenance-aware migration in that case.
75
+ Rehearse against a restored clone and keep a verified backup because type
76
+ upgrades have no automatic down migration. `smrt db:diff
77
+ --postgres-timestamp-legacy-timezone UTC` previews manifest-owned changes;
78
+ `smrt db:migrate --dry-run --postgres-timestamp-legacy-timezone UTC` also
79
+ queries and prints the read-only `_smrt_*` conversion plan without initializing
80
+ the tracker or writing to the database.
78
81
 
79
82
  ### Code Generation
80
83
 
@@ -5,7 +5,7 @@ import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, writeFile
5
5
  import * as path from "node:path";
6
6
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
7
7
  import { fileURLToPath, pathToFileURL } from "node:url";
8
- import { ObjectRegistry, SchemaComparer, createQualifiedName, generateDDLForEngine, getClassName, isQualifiedName, parseQualifiedName } from "@happyvertical/smrt-core";
8
+ import { ObjectRegistry, SchemaComparer, createQualifiedName, generateDDLForEngine, getClassName, isQualifiedName, migratePostgresSystemTimestamps, parseQualifiedName, planPostgresSystemTimestampMigrations } from "@happyvertical/smrt-core";
9
9
  import { loadExternalManifestSync } from "@happyvertical/smrt-core/manifest";
10
10
  import { access, cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
11
11
  import { createLogger } from "@happyvertical/logger";
@@ -7187,6 +7187,7 @@ export default testManifest;
7187
7187
  try {
7188
7188
  const forceSelection = resolveForceMigrationSelection(options.force, options["force-migration"]);
7189
7189
  const postgresTimestampMigration = resolvePostgresTimestampMigration(options["postgres-timestamp-legacy-timezone"]);
7190
+ const isDryRun = options["dry-run"] ?? false;
7190
7191
  const { getPackageConfig } = await import("@happyvertical/smrt-config");
7191
7192
  const { DEFAULT_CLI_CONFIG } = await import("./config-BwrFRL8L.js");
7192
7193
  const config = getPackageConfig("cli", DEFAULT_CLI_CONFIG);
@@ -7264,22 +7265,23 @@ export default testManifest;
7264
7265
  return;
7265
7266
  }
7266
7267
  console.log(`✓ Connected to ${formatDatabaseDisplayUrl(dbType, dbUrl)}\n`);
7268
+ const systemTimestampPreview = postgresTimestampMigration && isDryRun ? await planPostgresSystemTimestampMigrations(db, postgresTimestampMigration, dbType) : [];
7269
+ if (postgresTimestampMigration && !isDryRun) await migratePostgresSystemTimestamps(db, postgresTimestampMigration, dbType);
7267
7270
  const { MigrationTracker, shortChecksum } = await import("@happyvertical/smrt-core/migrations");
7268
7271
  const tracker = new MigrationTracker({
7269
7272
  db,
7270
7273
  useConcurrentIndexes: options["postgres-safe"] ?? false
7271
7274
  });
7272
- await tracker.initialize();
7275
+ if (!isDryRun) await tracker.initialize();
7273
7276
  if (options.verbose) {
7274
7277
  const engine = tracker.getEngine();
7275
- console.log(`Migration tracker initialized (engine: ${engine})`);
7278
+ console.log(isDryRun ? `Migration tracker preview configured (engine: ${engine})` : `Migration tracker initialized (engine: ${engine})`);
7276
7279
  if (options["postgres-safe"] && engine === "postgres") console.log("PostgreSQL-safe mode enabled (CONCURRENTLY, lock_timeout)");
7277
7280
  console.log();
7278
7281
  }
7279
7282
  const migrations = [];
7280
7283
  const manualInterventions = [];
7281
7284
  const tableErrorCount = 0;
7282
- const isDryRun = options["dry-run"] ?? false;
7283
7285
  const applySchemaMigrations = shouldApplySchemaMigrations({ dryRun: isDryRun });
7284
7286
  const repairData = Boolean(options["repair-data"] || options["upgrade-sti"]);
7285
7287
  if (options["upgrade-sti"]) {
@@ -7323,7 +7325,7 @@ export default testManifest;
7323
7325
  console.log(" Manual migration required (backup, recreate, restore as needed).\n");
7324
7326
  }
7325
7327
  const tablesCreated = diff.added_tables.length > 0;
7326
- const schemaUpToDate = migrations.length === 0 && manualInterventions.length === 0 && !tablesCreated;
7328
+ const schemaUpToDate = migrations.length === 0 && manualInterventions.length === 0 && !tablesCreated && systemTimestampPreview.length === 0;
7327
7329
  if (isDryRun) {
7328
7330
  if (schemaUpToDate && !repairData) {
7329
7331
  console.log("✅ Database schema is up to date - no migrations needed\n");
@@ -7332,6 +7334,11 @@ export default testManifest;
7332
7334
  if (schemaUpToDate) console.log("✅ Database schema is up to date - no schema migrations needed\n");
7333
7335
  else {
7334
7336
  console.log("📋 Migration Preview (not executed):\n");
7337
+ if (systemTimestampPreview.length > 0) {
7338
+ console.log(` 🕰️ SMRT system timestamp columns to convert: ${systemTimestampPreview.length}`);
7339
+ for (const migration of systemTimestampPreview) console.log(migration.kind === "column" ? ` ${migration.tableName}.${migration.columnName}` : " _smrt_changes append function signature");
7340
+ console.log();
7341
+ }
7335
7342
  const columnMigrations = migrations.filter((m) => m.type === "add_column");
7336
7343
  const indexMigrations = migrations.filter((m) => m.type === "add_index");
7337
7344
  const indexDrops = migrations.filter((m) => m.type === "drop_index");
@@ -7351,6 +7358,10 @@ export default testManifest;
7351
7358
  console.log();
7352
7359
  }
7353
7360
  console.log(" SQL Statements:\n");
7361
+ for (const migration of systemTimestampPreview) {
7362
+ const terminator = migration.sql.trimEnd().endsWith(";") ? "" : ";";
7363
+ console.log(` ${migration.sql}${terminator}`);
7364
+ }
7354
7365
  for (const m of migrations) {
7355
7366
  const sqlStatements = m.sqlStatements ?? (m.sql ? [m.sql] : []);
7356
7367
  for (const sql of sqlStatements) console.log(` ${sql};`);
package/dist/index.js CHANGED
@@ -48,56 +48,56 @@ var _docsCommands = null;
48
48
  var _playgroundCommands = null;
49
49
  async function getGnodeCommands() {
50
50
  if (!_gnodeCommands) {
51
- const { gnodeCommands } = await import("./commands-gjGWLmwD.js");
51
+ const { gnodeCommands } = await import("./commands-DA3gTMzR.js");
52
52
  _gnodeCommands = gnodeCommands;
53
53
  }
54
54
  return _gnodeCommands;
55
55
  }
56
56
  async function getGitCommands() {
57
57
  if (!_gitCommands) {
58
- const { gitCommands } = await import("./commands-gjGWLmwD.js");
58
+ const { gitCommands } = await import("./commands-DA3gTMzR.js");
59
59
  _gitCommands = gitCommands;
60
60
  }
61
61
  return _gitCommands;
62
62
  }
63
63
  async function getGenerateCommands() {
64
64
  if (!_generateCommands) {
65
- const { generateCommands } = await import("./commands-gjGWLmwD.js");
65
+ const { generateCommands } = await import("./commands-DA3gTMzR.js");
66
66
  _generateCommands = generateCommands;
67
67
  }
68
68
  return _generateCommands;
69
69
  }
70
70
  async function getInitCommands() {
71
71
  if (!_initCommands) {
72
- const { initCommands } = await import("./commands-gjGWLmwD.js");
72
+ const { initCommands } = await import("./commands-DA3gTMzR.js");
73
73
  _initCommands = initCommands;
74
74
  }
75
75
  return _initCommands;
76
76
  }
77
77
  async function getUtilityCommands() {
78
78
  if (!_utilityCommands) {
79
- const { utilityCommands } = await import("./commands-gjGWLmwD.js");
79
+ const { utilityCommands } = await import("./commands-DA3gTMzR.js");
80
80
  _utilityCommands = utilityCommands;
81
81
  }
82
82
  return _utilityCommands;
83
83
  }
84
84
  async function getDispatchCommands() {
85
85
  if (!_dispatchCommands) {
86
- const { dispatchCommands } = await import("./commands-gjGWLmwD.js");
86
+ const { dispatchCommands } = await import("./commands-DA3gTMzR.js");
87
87
  _dispatchCommands = dispatchCommands;
88
88
  }
89
89
  return _dispatchCommands;
90
90
  }
91
91
  async function getDocsCommands() {
92
92
  if (!_docsCommands) {
93
- const { docsCommands } = await import("./commands-gjGWLmwD.js");
93
+ const { docsCommands } = await import("./commands-DA3gTMzR.js");
94
94
  _docsCommands = docsCommands;
95
95
  }
96
96
  return _docsCommands;
97
97
  }
98
98
  async function getPlaygroundCommands() {
99
99
  if (!_playgroundCommands) {
100
- const { playgroundCommands } = await import("./commands-gjGWLmwD.js");
100
+ const { playgroundCommands } = await import("./commands-DA3gTMzR.js");
101
101
  _playgroundCommands = playgroundCommands;
102
102
  }
103
103
  return _playgroundCommands;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-cli",
3
- "version": "0.40.30",
3
+ "version": "0.40.32",
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.40.30",
36
- "@happyvertical/smrt-core": "0.40.30",
37
- "@happyvertical/smrt-dev-mcp": "0.40.30",
38
- "@happyvertical/smrt-config": "0.40.30",
39
- "@happyvertical/smrt-playground": "0.40.30",
40
- "@happyvertical/smrt-types": "0.40.30"
35
+ "@happyvertical/smrt-agents": "0.40.32",
36
+ "@happyvertical/smrt-core": "0.40.32",
37
+ "@happyvertical/smrt-playground": "0.40.32",
38
+ "@happyvertical/smrt-types": "0.40.32",
39
+ "@happyvertical/smrt-dev-mcp": "0.40.32",
40
+ "@happyvertical/smrt-config": "0.40.32"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "24.13.2",