{"version":3,"file":"cli.mjs","names":[],"sources":["../src/actions/generate-models.ts","../src/actions/migrations-create.ts","../src/actions/migrations-update.ts","../src/actions/migrations-drops.ts","../src/actions/schema-create.ts","../src/cli.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025-2026 Vasyl Zakharchenko\n// SPDX-License-Identifier: MIT\n\nimport \"reflect-metadata\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { execSync } from \"node:child_process\";\n\n/**\n * Options for model generation\n */\nexport interface GenerateModelsOptions {\n  host: string;\n  port: number;\n  user: string;\n  password: string;\n  dbName: string;\n  output: string;\n  versionField: string;\n}\n\n/**\n * Interface for column metadata\n */\ninterface ColumnMetadata {\n  autoincrement: boolean;\n  name: string;\n  type: string;\n  primaryKey: boolean;\n  notNull: boolean;\n}\n\n/**\n * Interface for table metadata\n */\ninterface TableMetadata {\n  name: string;\n  columns: Record<string, ColumnMetadata>;\n  compositePrimaryKeys: Record<string, { name: string; columns: string[] }>;\n  indexes: Record<string, unknown>;\n  foreignKeys: Record<string, unknown>;\n  uniqueConstraints: Record<string, unknown>;\n  checkConstraint: Record<string, unknown>;\n}\n\n/**\n * Interface for version field metadata\n */\ninterface VersionFieldMetadata {\n  fieldName: string;\n}\n\n/**\n * Interface for table version metadata\n */\ninterface TableVersionMetadata {\n  tableName: string;\n  versionField: VersionFieldMetadata;\n}\n\n/**\n * Type for additional metadata map\n */\ntype AdditionalMetadata = Record<string, TableVersionMetadata>;\n\n/**\n * Interface for journal entry\n */\ninterface JournalEntry {\n  idx: number;\n  version: string;\n  when: number;\n  tag: string;\n  breakpoints: boolean;\n}\n\n/**\n * Interface for journal data\n */\ninterface JournalData {\n  version: string;\n  dialect: string;\n  entries: JournalEntry[];\n}\n\n/**\n * Replaces MySQL types with custom types in the generated schema\n * @param schemaContent - The content of the generated schema file\n * @returns Modified schema content with custom types\n */\nfunction replaceMySQLTypes(schemaContent: string): string {\n  // Add imports at the top of the file\n  const imports = `import { forgeDateTimeString, forgeTimeString, forgeDateString, forgeTimestampString } from \"forge-sql-orm\";\\n\\n`;\n\n  // Replace types in the content\n  let modifiedContent = schemaContent\n    // Handle datetime with column name and mode option\n    .replace(\n      /datetime\\(['\"]([^'\"]+)['\"],\\s*{\\s*mode:\\s*['\"]string['\"]\\s*}\\)/g,\n      \"forgeDateTimeString('$1')\",\n    )\n    // Handle datetime with column name only\n    .replace(/datetime\\(['\"]([^'\"]+)['\"]\\)/g, \"forgeDateTimeString('$1')\")\n    // Handle datetime with mode option only\n    .replace(/datetime\\(\\s*{\\s*mode:\\s*['\"]string['\"]\\s*}\\s*\\)/g, \"forgeDateTimeString()\")\n    // Handle time with column name and mode option\n    .replace(/time\\(['\"]([^'\"]+)['\"],\\s*{\\s*mode:\\s*['\"]string['\"]\\s*}\\)/g, \"forgeTimeString('$1')\")\n    // Handle time with column name only\n    .replace(/time\\(['\"]([^'\"]+)['\"]\\)/g, \"forgeTimeString('$1')\")\n    // Handle time with mode option only\n    .replace(/time\\(\\s*{\\s*mode:\\s*['\"]string['\"]\\s*}\\s*\\)/g, \"forgeTimeString()\")\n    // Handle date with column name and mode option\n    .replace(/date\\(['\"]([^'\"]+)['\"],\\s*{\\s*mode:\\s*['\"]string['\"]\\s*}\\)/g, \"forgeDateString('$1')\")\n    // Handle date with column name only\n    .replace(/date\\(['\"]([^'\"]+)['\"]\\)/g, \"forgeDateString('$1')\")\n    // Handle date with mode option only\n    .replace(/date\\(\\s*{\\s*mode:\\s*['\"]string['\"]\\s*}\\s*\\)/g, \"forgeDateString()\")\n    // Handle timestamp with column name and mode option\n    .replace(\n      /timestamp\\(['\"]([^'\"]+)['\"],\\s*{\\s*mode:\\s*['\"]string['\"]\\s*}\\)/g,\n      \"forgeTimestampString('$1')\",\n    )\n    // Handle timestamp with column name only\n    .replace(/timestamp\\(['\"]([^'\"]+)['\"]\\)/g, \"forgeTimestampString('$1')\")\n    // Handle timestamp with mode option only\n    .replace(/timestamp\\(\\s*{\\s*mode:\\s*['\"]string['\"]\\s*}\\s*\\)/g, \"forgeTimestampString()\");\n\n  // Add imports if they don't exist\n  if (!modifiedContent.includes(\"import { forgeDateTimeString\")) {\n    modifiedContent = imports + modifiedContent;\n  }\n\n  return modifiedContent;\n}\n\n/** MySQL/Drizzle column types supported for optimistic-locking version fields. */\nconst SUPPORTED_VERSION_TYPES = new Set([\"datetime\", \"timestamp\", \"int\", \"number\", \"decimal\"]);\n\n/**\n * Validates a version-field column and returns its metadata, or undefined\n * (after logging a warning) when the column cannot be used for versioning.\n */\nfunction resolveVersionField(\n  tableName: string,\n  col: ColumnMetadata,\n): TableVersionMetadata | undefined {\n  if (col.notNull && SUPPORTED_VERSION_TYPES.has(col.type)) {\n    return { tableName, versionField: { fieldName: col.name } };\n  }\n\n  if (col.notNull) {\n    console.warn(\n      `Version field \"${col.name}\" in table ${tableName} has unsupported type \"${col.type}\". ` +\n        `Only datetime, timestamp, int, and decimal types are supported for versioning. Versioning will be skipped.`,\n    );\n  } else {\n    console.warn(\n      `Version field \"${col.name}\" in table ${tableName} is nullable. Versioning may not work correctly.`,\n    );\n  }\n  return undefined;\n}\n\n/**\n * Reads the drizzle snapshot and builds the version-metadata map for all tables.\n */\nfunction buildAdditionalMetadata(metaDir: string, versionFieldName: string): AdditionalMetadata {\n  const additionalMetadata: AdditionalMetadata = {};\n  const snapshotFile = path.join(metaDir, \"0000_snapshot.json\");\n  if (!fs.existsSync(snapshotFile)) {\n    return additionalMetadata;\n  }\n\n  const snapshotData = JSON.parse(fs.readFileSync(snapshotFile, \"utf-8\"));\n  for (const [tableName, tableData] of Object.entries(snapshotData.tables)) {\n    const table = tableData as TableMetadata;\n\n    if (tableName.toLowerCase().startsWith(\"a_\")) {\n      console.warn(\n        `⚠️  Table \"${tableName}\" starts with \"a_\". KVS Cache will not work with this table because such tables are ignored in cache operations.`,\n      );\n    }\n\n    const versionEntry = Object.entries(table.columns).find(\n      ([, col]) => col.name.toLowerCase() === versionFieldName,\n    );\n    if (!versionEntry) {\n      continue;\n    }\n\n    const metadata = resolveVersionField(tableName, versionEntry[1]);\n    if (metadata) {\n      additionalMetadata[tableName] = metadata;\n    }\n  }\n  return additionalMetadata;\n}\n\n/** Renders the generated `index.ts` exporting schema, relations and version metadata. */\nfunction renderVersionMetadata(additionalMetadata: AdditionalMetadata): string {\n  return `/**\n * This file was auto-generated by forge-sql-orm\n * Generated at: ${new Date().toISOString()}\n *\n * DO NOT EDIT THIS FILE MANUALLY\n * Any changes will be overwritten on next generation\n */\n\n\nexport * from \"./relations\";\nexport * from \"./schema\";\n\nexport interface VersionFieldMetadata {\n  fieldName: string;\n}\n\nexport interface TableMetadata {\n  tableName: string;\n  versionField: VersionFieldMetadata;\n}\n\nexport type AdditionalMetadata = Record<string, TableMetadata>;\n\nexport const additionalMetadata: AdditionalMetadata = ${JSON.stringify(additionalMetadata, null, 2)};\n`;\n}\n\n/** Rewrites MySQL column types in the generated schema to forge custom types. */\nfunction rewriteSchemaTypes(output: string): void {\n  const schemaPath = path.join(output, \"schema.ts\");\n  if (!fs.existsSync(schemaPath)) {\n    return;\n  }\n  fs.writeFileSync(schemaPath, replaceMySQLTypes(fs.readFileSync(schemaPath, \"utf-8\")));\n  console.log(`✅ Updated schema types in: ${schemaPath}`);\n}\n\n/** Removes drizzle-kit migration/meta artifacts that are not needed by forge-sql-orm. */\nfunction cleanupGeneratedArtifacts(output: string, metaDir: string): void {\n  const migrationDir = path.join(output, \"migrations\");\n  if (fs.existsSync(migrationDir)) {\n    fs.rmSync(migrationDir, { recursive: true, force: true });\n    console.log(`✅ Removed: ${migrationDir}`);\n  }\n\n  if (!fs.existsSync(metaDir)) {\n    return;\n  }\n\n  const journalFile = path.join(metaDir, \"_journal.json\");\n  if (fs.existsSync(journalFile)) {\n    const journalData = JSON.parse(fs.readFileSync(journalFile, \"utf-8\")) as JournalData;\n    for (const entry of journalData.entries) {\n      const sqlFile = path.join(output, `${entry.tag}.sql`);\n      if (fs.existsSync(sqlFile)) {\n        fs.rmSync(sqlFile, { force: true });\n        console.log(`✅ Removed SQL file: ${entry.tag}.sql`);\n      }\n    }\n  }\n\n  fs.rmSync(metaDir, { recursive: true, force: true });\n  console.log(`✅ Removed: ${metaDir}`);\n}\n\n/**\n * Generates models for all tables in the database using drizzle-kit\n * @param options - Generation options\n */\nexport const generateModels = async (options: GenerateModelsOptions) => {\n  try {\n    // Generate models using drizzle-kit pull\n    execSync(\n      `npx drizzle-kit pull --dialect mysql --url mysql://${options.user}:${options.password}@${options.host}:${options.port}/${options.dbName} --out ${options.output}`,\n      { encoding: \"utf-8\" },\n    );\n\n    const metaDir = path.join(options.output, \"meta\");\n    const additionalMetadata = fs.existsSync(metaDir)\n      ? buildAdditionalMetadata(metaDir, options.versionField)\n      : {};\n\n    fs.writeFileSync(\n      path.join(options.output, \"index.ts\"),\n      renderVersionMetadata(additionalMetadata),\n    );\n\n    rewriteSchemaTypes(options.output);\n    cleanupGeneratedArtifacts(options.output, metaDir);\n\n    console.log(`✅ Successfully generated models and version metadata`);\n    process.exit(0);\n  } catch (error) {\n    console.error(`❌ Error during model generation:`, error);\n    process.exit(1);\n  }\n};\n","// SPDX-FileCopyrightText: 2025-2026 Vasyl Zakharchenko\n// SPDX-License-Identifier: MIT\n\nimport \"reflect-metadata\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport mysql from \"mysql2/promise\";\nimport { RowDataPacket } from \"mysql2\";\n\n/**\n * Options for migration creation\n */\nexport interface CreateMigrationOptions {\n  output: string;\n  entitiesPath: string;\n  force?: boolean;\n  host?: string;\n  port?: number;\n  user?: string;\n  password?: string;\n  dbName?: string;\n}\n\ninterface CreateTableRow extends RowDataPacket {\n  Table: string;\n  \"Create Table\": string;\n}\n\n/**\n * Loads the current migration version from `migrationCount.ts`.\n * @param migrationPath - Path to the migration folder.\n * @returns The latest migration version.\n */\nexport const loadMigrationVersion = async (migrationPath: string): Promise<number> => {\n  try {\n    const migrationCountFilePath = path.resolve(path.join(migrationPath, \"migrationCount.ts\"));\n    if (!fs.existsSync(migrationCountFilePath)) {\n      console.log(`✅ Current migration version: 0`);\n      return 0;\n    }\n\n    const { MIGRATION_VERSION } = await import(migrationCountFilePath);\n    console.log(`✅ Current migration version: ${MIGRATION_VERSION}`);\n    return MIGRATION_VERSION as number;\n  } catch (error) {\n    console.error(`❌ Error loading migrationCount:`, error);\n    process.exit(1);\n  }\n};\n\n/**\n * Regular expressions for adding IF NOT EXISTS to SQL statements\n * Note: MySQL/TiDB does not support IF NOT EXISTS for ALTER TABLE ADD CONSTRAINT\n */\nconst SQL_KIND_REGEX = /CREATE (?!.*IF NOT EXISTS)(UNIQUE INDEX|INDEX|TABLE) /gim;\n\n/**\n * Inserts IF NOT EXISTS into CREATE statements.\n * Only adds IF NOT EXISTS to CREATE TABLE, CREATE INDEX, and CREATE UNIQUE INDEX.\n * Does not add IF NOT EXISTS to ALTER TABLE statements as MySQL/TiDB doesn't support it.\n * @param content - The SQL content.\n * @returns The SQL content with IF NOT EXISTS added.\n */\nfunction insertNotExists(content: string): string {\n  SQL_KIND_REGEX.lastIndex = 0;\n\n  // Add IF NOT EXISTS to CREATE TABLE, CREATE INDEX, CREATE UNIQUE INDEX\n  // Note: ALTER TABLE ADD CONSTRAINT and ALTER TABLE ADD INDEX don't support IF NOT EXISTS in MySQL/TiDB\n  content = content.replace(SQL_KIND_REGEX, \"CREATE $1 IF NOT EXISTS \");\n\n  return content;\n}\n\n/**\n * Cleans SQL statements by removing unnecessary database options.\n * @param sql - The raw SQL statement.\n * @returns The cleaned SQL statement.\n */\nexport function cleanSQLStatement(sql: string): string {\n  // Add IF NOT EXISTS to relevant statements\n  sql = insertNotExists(sql);\n\n  // Remove unnecessary database options\n  return sql.replace(/\\s+default\\s+character\\s+set\\s+utf8mb4\\s+engine\\s*=\\s*InnoDB;?/gi, \"\").trim();\n}\n\n/**\n * Generates a migration file using the provided SQL statements.\n * @param createStatements - Array of SQL statements.\n * @param version - Migration version number.\n * @returns TypeScript migration file content.\n */\nexport function generateMigrationFile(createStatements: string[], version: number): string {\n  const versionPrefix = `v${version}_MIGRATION`;\n\n  // Clean each SQL statement and generate migration lines with .enqueue()\n  const migrationLines = createStatements\n    .map(\n      (stmt, index) =>\n        `        .enqueue(\"${versionPrefix}${index}\", \"${cleanSQLStatement(stmt).replace(/\\s+/g, \" \")}\")`,\n    )\n    .join(\"\\n\");\n\n  // Migration template\n  return `import { MigrationRunner } from \"@forge/sql/out/migration\";\n\nexport default (migrationRunner: MigrationRunner): MigrationRunner => {\n    return migrationRunner\n${migrationLines};\n};`;\n}\n\n/**\n * Saves the generated migration file along with `migrationCount.ts` and `index.ts`.\n * @param migrationCode - The migration code to be written to the file.\n * @param version - Migration version number.\n * @param outputDir - Directory where the migration files will be saved.\n */\nexport function saveMigrationFiles(migrationCode: string, version: number, outputDir: string) {\n  if (!fs.existsSync(outputDir)) {\n    fs.mkdirSync(outputDir, { recursive: true });\n  }\n\n  const migrationFilePath = path.join(outputDir, `migrationV${version}.ts`);\n  const migrationCountPath = path.join(outputDir, `migrationCount.ts`);\n  const indexFilePath = path.join(outputDir, `index.ts`);\n\n  // Write the migration file\n  fs.writeFileSync(migrationFilePath, migrationCode);\n\n  // Write the migration count file\n  fs.writeFileSync(migrationCountPath, `export const MIGRATION_VERSION = ${version};`);\n\n  // Generate the migration index file with static imports\n  // Build import lines for each migration version\n  const importLines = [];\n  for (let i = 1; i <= version; i++) {\n    importLines.push(`import v${i} from \"./migrationV${i}\";`);\n  }\n  // Build call lines for each migration version\n  const callLines = [];\n  for (let i = 1; i <= version; i++) {\n    callLines.push(`  v${i}(migrationRunner);`);\n  }\n  const indexFileContent = `import { MigrationRunner } from \"@forge/sql/out/migration\";\n${importLines.join(\"\\n\")}\n\nexport type MigrationType = (\n  migrationRunner: MigrationRunner,\n) => MigrationRunner;\n\nexport default async (\n  migrationRunner: MigrationRunner,\n): Promise<MigrationRunner> => {\n${callLines.join(\"\\n\")}\n  return migrationRunner;\n};`;\n\n  fs.writeFileSync(indexFilePath, indexFileContent);\n\n  console.log(`✅ Migration file created: ${migrationFilePath}`);\n  console.log(`✅ Migration count file updated: ${migrationCountPath}`);\n  console.log(`✅ Migration index file created: ${indexFilePath}`);\n}\n\n/**\n * Gets list of tables from the database\n * @param connection - MySQL connection\n * @returns Array of table names\n */\nasync function getTables(connection: mysql.Connection): Promise<string[]> {\n  const [rows] = await connection.execute<RowDataPacket[]>(\"SHOW TABLES\");\n  return rows.map((row) => Object.values(row)[0] as string);\n}\n\n/**\n * Gets CREATE TABLE statement for a specific table\n * @param connection - MySQL connection\n * @param tableName - Name of the table\n * @returns CREATE TABLE statement\n */\nasync function getCreateTableStatement(\n  connection: mysql.Connection,\n  tableName: string,\n): Promise<string | null> {\n  const [rows] = await connection.execute<CreateTableRow[]>(`SHOW CREATE TABLE \\`${tableName}\\``);\n  if (rows.length > 0 && rows[0][\"Create Table\"]) {\n    return rows[0][\"Create Table\"];\n  }\n  return null;\n}\n\n/**\n * Gets all CREATE TABLE statements from the database\n * @param connection - MySQL connection\n * @returns Array of CREATE TABLE statements\n */\nasync function getAllCreateTableStatements(connection: mysql.Connection): Promise<string[]> {\n  const tables = await getTables(connection);\n  const statements: string[] = [];\n\n  for (const table of tables) {\n    const createTable = await getCreateTableStatement(connection, table);\n    if (createTable) {\n      statements.push(createTable);\n    }\n  }\n\n  return statements;\n}\n\n/**\n * Creates a full database migration.\n * @param options - Database connection settings and output paths.\n */\nexport const createMigration = async (options: CreateMigrationOptions) => {\n  try {\n    let version = await loadMigrationVersion(options.output);\n\n    if (version > 0) {\n      if (options.force) {\n        console.warn(\n          `⚠️ Warning: Migration already exists. Creating new migration with force flag...`,\n        );\n      } else {\n        console.error(\n          `❌ Error: Migration has already been created. Use --force flag to override.`,\n        );\n        process.exit(1);\n      }\n    }\n\n    // Validate database connection parameters\n    if (!options.host || !options.port || !options.user || !options.password || !options.dbName) {\n      console.error(\n        `❌ Error: Database connection parameters are required (host, port, user, password, dbName)`,\n      );\n      process.exit(1);\n    }\n\n    // Create database connection\n    const connection = await mysql.createConnection({\n      host: options.host,\n      port: options.port,\n      user: options.user,\n      password: options.password,\n      database: options.dbName,\n    });\n\n    try {\n      console.log(`✅ Connected to database: ${options.dbName}`);\n\n      // Get all CREATE TABLE statements from the database\n      console.log(`📋 Fetching CREATE TABLE statements from database...`);\n      const createStatements = await getAllCreateTableStatements(connection);\n\n      if (createStatements.length === 0) {\n        console.warn(`⚠️ Warning: No tables found in the database.`);\n      } else {\n        console.log(`✅ Found ${createStatements.length} table(s)`);\n      }\n\n      // Generate and save migration files\n      const migrationFile = generateMigrationFile(createStatements, 1);\n      saveMigrationFiles(migrationFile, 1, options.output);\n\n      console.log(`✅ Migration successfully created!`);\n      process.exit(0);\n    } finally {\n      await connection.end();\n    }\n  } catch (error) {\n    console.error(`❌ Error during migration creation:`, error);\n    process.exit(1);\n  }\n};\n","// SPDX-FileCopyrightText: 2025-2026 Vasyl Zakharchenko\n// SPDX-License-Identifier: MIT\n\nimport \"reflect-metadata\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport mysql from \"mysql2/promise\";\nimport { AnyMySqlTable, MySqlTable, TableConfig } from \"drizzle-orm/mysql-core\";\nimport { RowDataPacket } from \"mysql2\";\nimport { getTableMetadata } from \"forge-sql-orm\";\nimport { AnyIndexBuilder } from \"drizzle-orm/mysql-core/indexes\";\nimport { ForeignKeyBuilder } from \"drizzle-orm/mysql-core/foreign-keys\";\nimport { UniqueConstraintBuilder } from \"drizzle-orm/mysql-core/unique-constraint\";\nimport { v4 as uuid } from \"uuid\";\n\n/**\n * Options for updating an existing migration.\n */\nexport interface UpdateMigrationOptions {\n  output: string;\n  entitiesPath: string;\n  host: string;\n  port: number;\n  user: string;\n  password: string;\n  dbName: string;\n}\n\ninterface DrizzleColumn {\n  type: string;\n  notNull: boolean;\n  autoincrement?: boolean;\n  columnType?: string;\n  name: string;\n  default?: string;\n  getSQLType: () => string;\n}\n\n/**\n * Minimal shape of a Drizzle SQL default expression that exposes `toQuery`.\n */\ninterface ToQueryable {\n  toQuery: (config: Record<string, unknown>) => { sql: string };\n}\n\n/**\n * Type guard for default values that expose a `toQuery` method (SQL expressions).\n */\nfunction isToQueryable(value: unknown): value is ToQueryable {\n  return (\n    typeof value === \"object\" &&\n    value !== null &&\n    typeof (value as { toQuery?: unknown }).toQuery === \"function\"\n  );\n}\n\ninterface DrizzleSchema {\n  [tableName: string]: {\n    [columnName: string]: DrizzleColumn;\n  };\n}\n\ninterface DatabaseColumn extends RowDataPacket {\n  TABLE_NAME: string;\n  COLUMN_NAME: string;\n  COLUMN_TYPE: string;\n  IS_NULLABLE: string;\n  COLUMN_KEY: string;\n  EXTRA: string;\n}\n\ninterface DatabaseIndex extends RowDataPacket {\n  TABLE_NAME: string;\n  INDEX_NAME: string;\n  COLUMN_NAME: string;\n  NON_UNIQUE: number;\n}\n\ninterface DatabaseForeignKey extends RowDataPacket {\n  TABLE_NAME: string;\n  COLUMN_NAME: string;\n  CONSTRAINT_NAME: string;\n  REFERENCED_TABLE_NAME: string;\n  REFERENCED_COLUMN_NAME: string;\n}\n\ninterface TableSchema {\n  columns: Record<string, DatabaseColumn>;\n  indexes: Record<\n    string,\n    {\n      columns: string[];\n      unique: boolean;\n    }\n  >;\n  foreignKeys: Record<\n    string,\n    {\n      column: string;\n      referencedTable: string;\n      referencedColumn: string;\n    }\n  >;\n}\n\ninterface DatabaseSchema {\n  [tableName: string]: TableSchema;\n}\n\ntype PreMigrationNotNull = {\n  tableName: string;\n  dbTable: TableSchema;\n  colName: string;\n  type: string;\n  migrationType: \"NEW_FIELD_NOT_NULL\" | \"MODIFY_NOT_NULL\" | \"INLINE\";\n  defaultValue: string;\n};\n\nfunction buildDefault(preMigration: PreMigrationNotNull): string {\n  const def = preMigration.defaultValue;\n  const type = preMigration.type.toLowerCase();\n\n  // No default defined\n  if (def === undefined || def === null) {\n    return \"\";\n  }\n\n  // Empty string default → DEFAULT ''\n  if (def === \"\") {\n    return `''`;\n  }\n\n  // Types that must be quoted\n  const stringTypes = new Set([\n    \"char\",\n    \"varchar\",\n    \"text\",\n    \"tinytext\",\n    \"mediumtext\",\n    \"longtext\",\n    \"enum\",\n    \"set\",\n    \"binary\",\n    \"varbinary\",\n    \"blob\",\n  ]);\n\n  // Numeric types that accept numeric literals\n  const numericTypes = new Set([\n    \"tinyint\",\n    \"smallint\",\n    \"mediumint\",\n    \"int\",\n    \"bigint\",\n    \"decimal\",\n    \"float\",\n    \"double\",\n    \"bit\",\n  ]);\n\n  // Check if default value is a numeric literal\n  const isNumericLiteral = /^[+-]?\\d+(\\.\\d+)?$/.test(def);\n\n  // Numeric types → DEFAULT 123 (no quotes)\n  if (numericTypes.has(type) && isNumericLiteral) {\n    return `${def}`;\n  }\n\n  // String types → DEFAULT 'value'\n  if (stringTypes.has(type)) {\n    // Double escape single quotes\n    const escaped = def.replace(/'/g, \"''\");\n    return `'${escaped}'`;\n  }\n\n  // Other types: treat default as an expression\n  // e.g. DEFAULT CURRENT_TIMESTAMP, DEFAULT (uuid()), DEFAULT now()\n  return `${def}`;\n}\n\n/**\n * Generates warning message for missing default value\n */\nfunction generateWarningMessage(tableName: string, colName: string, version: number): string {\n  return (\n    `⚠️  WARNING: Field \\`${tableName}\\`.\\`${colName}\\` requires a default value for existing NULL records.\\n` +\n    `   Action required in migration file: migrationV${version}.ts\\n` +\n    `   Find the line with: UPDATE \\`${tableName}\\` SET \\`${colName}\\` = ?\\n` +\n    `   Replace '?' with an actual value (e.g., '' for strings, 0 for numbers, '1970-01-01' for dates)\\n` +\n    `   OR remove this migration if it's not needed.`\n  );\n}\n\n/**\n * Handles warning for missing default value\n */\nfunction handleMissingDefaultValue(\n  preMigration: PreMigrationNotNull,\n  version: number,\n  migrationLineList: string[],\n): void {\n  const warningMsg = generateWarningMessage(preMigration.tableName, preMigration.colName, version);\n  console.warn(warningMsg);\n  migrationLineList.push(`console.error(${JSON.stringify(warningMsg)});`);\n}\n\n/**\n * Gets the default value for UPDATE statement\n */\nfunction getUpdateDefaultValue(preMigration: PreMigrationNotNull, defaultValue: string): string {\n  return defaultValue === \"?\" ? defaultValue : buildDefault(preMigration);\n}\n\n/**\n * Generates UPDATE statement for existing NULL records\n */\nfunction generateUpdateStatement(preMigration: PreMigrationNotNull, defaultValue: string): string {\n  const updateValue = getUpdateDefaultValue(preMigration, defaultValue);\n  return `UPDATE \\`${preMigration.tableName}\\` SET \\`${preMigration.colName}\\` = ${updateValue} WHERE \\`${preMigration.colName}\\` IS NULL`;\n}\n\n/**\n * Generates a migration file using the provided SQL statements.\n * @param createStatements - Array of SQL statements.\n * @param version - Migration version number.\n * @returns TypeScript migration file content.\n */\nfunction generateMigrationFile(\n  createStatements: {\n    changes: { change: string; premigrationId?: string }[];\n    preMigrations: Record<string, PreMigrationNotNull>;\n  },\n  version: number,\n): string {\n  const versionPrefix = `v${version}_MIGRATION`;\n  const migrationLineList: string[] = [];\n\n  createStatements.changes.forEach((change, index) => {\n    if (!change.premigrationId) {\n      // Regular change without pre-migration\n      migrationLineList.push(\n        `\\nmigrationRunner.enqueue(\"${versionPrefix}${index}\", \"${change.change}\")`,\n      );\n      return;\n    }\n\n    const preMigration = createStatements.preMigrations[change.premigrationId];\n    if (!preMigration) {\n      // Pre-migration ID exists but pre-migration not found\n      migrationLineList.push(\n        `\\nmigrationRunner.enqueue(\"${versionPrefix}${index}\", \"${change.change}\")`,\n      );\n      return;\n    }\n\n    const defaultValue = preMigration.defaultValue ?? \"?\";\n    const needsWarning = defaultValue === \"?\";\n\n    if (preMigration.migrationType === \"NEW_FIELD_NOT_NULL\") {\n      // Step 1: Add column as NULL\n      const addColumnStatement = change.change.replace(\"NOT NULL\", \"NULL\");\n      migrationLineList.push(\n        `\\nmigrationRunner.enqueue(\"${versionPrefix}${index}_NULLABLE\", \"${addColumnStatement}\");`,\n      );\n\n      // Step 2: Warning if default value is missing\n      if (needsWarning) {\n        handleMissingDefaultValue(preMigration, version, migrationLineList);\n      }\n\n      // Step 3: Update existing NULL records\n      const updateStatement = generateUpdateStatement(preMigration, defaultValue);\n      migrationLineList.push(\n        `\\nmigrationRunner.enqueue(\"${versionPrefix}${index}_UPDATE_EXISTS_RECORDS\", \"${updateStatement}\");`,\n      );\n\n      // Step 4: Modify column to NOT NULL\n      const defaultClause = defaultValue === \"?\" ? \"\" : ` DEFAULT ${buildDefault(preMigration)}`;\n      const modifyStatement = `ALTER TABLE \\`${preMigration.tableName}\\` MODIFY COLUMN IF EXISTS \\`${preMigration.colName}\\` ${preMigration.type} NOT NULL${defaultClause};`;\n      migrationLineList.push(\n        `\\nmigrationRunner.enqueue(\"${versionPrefix}${index}\", \"${modifyStatement}\");`,\n      );\n    } else if (preMigration.migrationType === \"MODIFY_NOT_NULL\") {\n      // Step 1: Warning if default value is missing\n      if (needsWarning) {\n        handleMissingDefaultValue(preMigration, version, migrationLineList);\n      }\n\n      // Step 2: Update existing NULL records, then apply the MODIFY statement\n      const updateStatement = generateUpdateStatement(preMigration, defaultValue);\n      migrationLineList.push(\n        `\\nmigrationRunner.enqueue(\"${versionPrefix}${index}_UPDATE_EXISTS_RECORDS\", \"${updateStatement}\")`,\n        `\\nmigrationRunner.enqueue(\"${versionPrefix}${index}\", \"${change.change}\")`,\n      );\n    }\n  });\n\n  const migrationLines = migrationLineList.join(\"\\n\");\n\n  return `import { MigrationRunner } from \"@forge/sql/out/migration\";\n\nexport default (migrationRunner: MigrationRunner): MigrationRunner => { \n${migrationLines};\nreturn migrationRunner;\n};`;\n}\n\n/** Captures the SQL statement (2nd arg) from a `.enqueue(\"id\", \"sql\")` call. */\nconst ENQUEUE_STATEMENT_REGEX = /\\.enqueue\\([^,]+,\\s*\"([^\"]+)\"/;\n\n/**\n * Filters out SQL statements that already exist in the previous migration file\n * @param newStatements - Array of SQL statements from new migration\n * @param prevVersion - Previous migration version\n * @param outputDir - Directory where migration files are stored\n * @returns Array of SQL statements that don't exist in previous migration\n */\nfunction filterWithPreviousMigration(\n  newStatements: {\n    changes: { change: string; premigrationId?: string }[];\n    preMigrations: Record<string, PreMigrationNotNull>;\n  },\n  prevVersion: number,\n  outputDir: string,\n): {\n  changes: { change: string; premigrationId?: string }[];\n  preMigrations: Record<string, PreMigrationNotNull>;\n} {\n  const prevMigrationPath = path.join(outputDir, `migrationV${prevVersion}.ts`);\n\n  if (!fs.existsSync(prevMigrationPath)) {\n    return {\n      changes: newStatements.changes.map((s) => ({\n        change: s.change.replace(/\\s+/g, \" \"),\n        premigrationId: s.premigrationId,\n      })),\n      preMigrations: newStatements.preMigrations,\n    };\n  }\n\n  // Read previous migration file\n  const prevContent = fs.readFileSync(prevMigrationPath, \"utf-8\");\n\n  // Extract SQL statements from the file into a Set for O(1) existence checks\n  const prevStatements = new Set(\n    prevContent\n      .split(\"\\n\")\n      .filter((line) => line.includes(\".enqueue(\"))\n      .map((line) => {\n        const match = ENQUEUE_STATEMENT_REGEX.exec(line);\n        return match ? match[1].replace(/\\s+/g, \" \").trim() : \"\";\n      }),\n  );\n\n  // Filter out statements that already exist in previous migration\n  return {\n    preMigrations: newStatements.preMigrations,\n    changes: newStatements.changes\n      .filter((s) => !prevStatements.has(s.change.replace(/\\s+/g, \" \")))\n      .map((s) => ({ change: s.change.replace(/\\s+/g, \" \"), premigrationId: s.premigrationId })),\n  };\n}\n\n/**\n * Saves the generated migration file along with `migrationCount.ts` and `index.ts`.\n * @param migrationCode - The migration code to be written to the file.\n * @param version - Migration version number.\n * @param outputDir - Directory where the migration files will be saved.\n * @returns boolean indicating if migration was saved\n */\nfunction saveMigrationFiles(migrationCode: string, version: number, outputDir: string): boolean {\n  if (!fs.existsSync(outputDir)) {\n    fs.mkdirSync(outputDir, { recursive: true });\n  }\n\n  const migrationFilePath = path.join(outputDir, `migrationV${version}.ts`);\n  const migrationCountPath = path.join(outputDir, `migrationCount.ts`);\n  const indexFilePath = path.join(outputDir, `index.ts`);\n\n  // Write the migration file\n  fs.writeFileSync(migrationFilePath, migrationCode);\n\n  // Write the migration count file\n  fs.writeFileSync(migrationCountPath, `export const MIGRATION_VERSION = ${version};`);\n\n  // Generate the migration index file with static imports\n  const importLines: string[] = [];\n  const callLines: string[] = [];\n\n  for (let i = 1; i <= version; i++) {\n    importLines.push(`import migrationV${i} from \"./migrationV${i}\";`);\n    callLines.push(`  migrationV${i}(migrationRunner);`);\n  }\n\n  const indexFileContent = `import { MigrationRunner } from \"@forge/sql/out/migration\";\n${importLines.join(\"\\n\")}\n\nexport type MigrationType = (\n  migrationRunner: MigrationRunner,\n) => MigrationRunner;\n\nexport default (\n  migrationRunner: MigrationRunner,\n): MigrationRunner => {\n${callLines.join(\"\\n\")}\n  return migrationRunner;\n};`;\n\n  fs.writeFileSync(indexFilePath, indexFileContent);\n\n  console.log(`✅ Migration file created: ${migrationFilePath}`);\n  console.log(`✅ Migration count file updated: ${migrationCountPath}`);\n  console.log(`✅ Migration index file created: ${indexFilePath}`);\n\n  return true;\n}\n\n/**\n * Loads the current migration version from `migrationCount.ts`.\n * @param migrationPath - Path to the migration folder.\n * @returns The latest migration version.\n */\nconst loadMigrationVersion = async (migrationPath: string): Promise<number> => {\n  try {\n    const migrationCountFilePath = path.resolve(path.join(migrationPath, \"migrationCount.ts\"));\n    if (!fs.existsSync(migrationCountFilePath)) {\n      console.warn(\n        `⚠️ Warning: migrationCount.ts not found in ${migrationCountFilePath}, assuming no previous migrations.`,\n      );\n      return 0;\n    }\n\n    const { MIGRATION_VERSION } = await import(migrationCountFilePath);\n    console.log(`✅ Current migration version: ${MIGRATION_VERSION}`);\n    return MIGRATION_VERSION as number;\n  } catch (error) {\n    console.error(`❌ Error loading migrationCount:`, error);\n    process.exit(1);\n  }\n};\n\n/**\n * Gets the current database schema from MySQL including indexes and foreign keys\n * @param connection - MySQL connection\n * @param dbName - Database name\n * @returns Database schema object with indexes and foreign keys\n */\nasync function getDatabaseSchema(\n  connection: mysql.Connection,\n  dbName: string,\n): Promise<DatabaseSchema> {\n  // Get columns\n  const [columns] = await connection.execute<DatabaseColumn[]>(\n    `\n    SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT\n    FROM INFORMATION_SCHEMA.COLUMNS\n    WHERE TABLE_SCHEMA = ?\n  `,\n    [dbName],\n  );\n\n  // Get indexes\n  const [indexes] = await connection.execute<DatabaseIndex[]>(\n    `\n    SELECT TABLE_NAME, INDEX_NAME, COLUMN_NAME, NON_UNIQUE\n    FROM INFORMATION_SCHEMA.STATISTICS\n    WHERE TABLE_SCHEMA = ?\n    ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX\n  `,\n    [dbName],\n  );\n\n  // Get foreign keys\n  const [foreignKeys] = await connection.execute<DatabaseForeignKey[]>(\n    `\n    SELECT \n      TABLE_NAME,\n      COLUMN_NAME,\n      CONSTRAINT_NAME,\n      REFERENCED_TABLE_NAME,\n      REFERENCED_COLUMN_NAME\n    FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE\n    WHERE TABLE_SCHEMA = ?\n    AND REFERENCED_TABLE_NAME IS NOT NULL\n  `,\n    [dbName],\n  );\n\n  const schema: DatabaseSchema = {};\n\n  // Process columns\n  columns.forEach((row) => {\n    if (!schema[row.TABLE_NAME]) {\n      schema[row.TABLE_NAME] = {\n        columns: {},\n        indexes: {},\n        foreignKeys: {},\n      };\n    }\n    schema[row.TABLE_NAME].columns[row.COLUMN_NAME] = row;\n  });\n\n  // Process indexes\n  indexes.forEach((row) => {\n    if (!schema[row.TABLE_NAME].indexes[row.INDEX_NAME]) {\n      schema[row.TABLE_NAME].indexes[row.INDEX_NAME] = {\n        columns: [],\n        unique: !row.NON_UNIQUE,\n      };\n    }\n    schema[row.TABLE_NAME].indexes[row.INDEX_NAME].columns.push(row.COLUMN_NAME);\n  });\n\n  // Process foreign keys\n  foreignKeys.forEach((row) => {\n    if (!schema[row.TABLE_NAME].foreignKeys[row.CONSTRAINT_NAME]) {\n      schema[row.TABLE_NAME].foreignKeys[row.CONSTRAINT_NAME] = {\n        column: row.COLUMN_NAME,\n        referencedTable: row.REFERENCED_TABLE_NAME,\n        referencedColumn: row.REFERENCED_COLUMN_NAME,\n      };\n    }\n  });\n\n  return schema;\n}\n\n/**\n * Converts MySQL type to normalized format for comparison\n * @param mysqlType - MySQL type from INFORMATION_SCHEMA or Drizzle type\n * @returns Normalized type string\n */\nfunction normalizeMySQLType(mysqlType: string): string {\n  // Remove length/precision information\n  let normalized = mysqlType.replace(/\\([^)]*\\)/, \"\").toLowerCase();\n\n  // Remove 'mysql' prefix from Drizzle types\n  normalized = normalized.replace(/^mysql/, \"\");\n\n  return normalized;\n}\n\n/**\n * Gets the name of a foreign key constraint\n * @param fk - The foreign key builder\n * @returns The name of the foreign key constraint\n */\nfunction getForeignKeyName(fk: ForeignKeyBuilder): string {\n  // @ts-ignore - Internal property access\n  return fk.name;\n}\n\n/**\n * Gets the name of an index\n * @param index - The index builder\n * @returns The name of the index\n */\nfunction getIndexName(index: AnyIndexBuilder): string {\n  // @ts-ignore - Internal property access\n  return index.name;\n}\n\n/**\n * Gets the name of a unique constraint\n * @param uc - The unique constraint builder\n * @returns The name of the unique constraint\n */\nfunction getUniqueConstraintName(uc: UniqueConstraintBuilder): string {\n  // @ts-ignore - Internal property access\n  return uc.name;\n}\n\n/**\n * Gets the columns of an index\n * @param index - The index builder\n * @returns Array of column names\n */\nfunction getIndexColumns(index: AnyIndexBuilder): string[] {\n  // @ts-ignore - Internal property access\n  return index.columns.map((col) => col.name);\n}\n\n/** Locale-aware comparator for sorting column-name arrays deterministically. */\nfunction compareColumnNames(a: string, b: string): number {\n  return a.localeCompare(b);\n}\n\nfunction compareForeignKey(\n  fk: ForeignKeyBuilder,\n  { columns }: { columns: string[]; unique: boolean },\n) {\n  // @ts-ignore\n  const fcolumns: string[] = fk.columns.map((c) => c.name);\n  return (\n    fcolumns.toSorted(compareColumnNames).join(\",\") ===\n    columns.toSorted(compareColumnNames).join(\",\")\n  );\n}\n\ntype SchemaChange = { change: string; premigrationId?: string };\ntype TableMetadataInfo = ReturnType<typeof getTableMetadata>;\n\n/** Builds CREATE TABLE + index + foreign-key statements for a table missing from the schema. */\nfunction buildNewTableChanges(tableName: string, dbTable: TableSchema): SchemaChange[] {\n  const changes: SchemaChange[] = [];\n\n  const columnDefs = Object.entries(dbTable.columns)\n    .map(([colName, col]) => {\n      const nullable = col.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n      const autoIncrement = col.EXTRA.includes(\"auto_increment\") ? \"AUTO_INCREMENT\" : \"\";\n      return `\\`${colName}\\` ${col.COLUMN_TYPE} ${nullable} ${autoIncrement}`.trim();\n    })\n    .join(\",\\n  \");\n  changes.push({ change: `CREATE TABLE if not exists \\`${tableName}\\` (\\n  ${columnDefs}\\n);` });\n\n  for (const [indexName, dbIndex] of Object.entries(dbTable.indexes)) {\n    if (indexName === \"PRIMARY\") {\n      continue;\n    }\n    const isForeignKeyIndex = dbIndex.columns.some((colName) => {\n      const column = dbTable.columns[colName];\n      return column?.COLUMN_KEY === \"MUL\" && column?.EXTRA.includes(\"foreign key\");\n    });\n    if (isForeignKeyIndex) {\n      continue;\n    }\n    const cols = dbIndex.columns.map((col) => `\\`${col}\\``).join(\", \");\n    const unique = dbIndex.unique ? \"UNIQUE \" : \"\";\n    changes.push({\n      change: `CREATE  ${unique}INDEX if not exists  \\`${indexName}\\` ON \\`${tableName}\\` (${cols});`,\n    });\n  }\n\n  for (const [fkName, dbFK] of Object.entries(dbTable.foreignKeys)) {\n    changes.push({\n      change: `ALTER TABLE \\`${tableName}\\` ADD CONSTRAINT \\`${fkName}\\` FOREIGN KEY (\\`${dbFK.column}\\`) REFERENCES \\`${dbFK.referencedTable}\\` (\\`${dbFK.referencedColumn}\\`);`,\n    });\n  }\n\n  return changes;\n}\n\n/** Builds an ADD COLUMN statement for a database column missing from the schema. */\nfunction buildAddColumnChange(\n  tableName: string,\n  dbTable: TableSchema,\n  colName: string,\n  dbCol: DatabaseColumn,\n  preMigrations: Record<string, PreMigrationNotNull>,\n): SchemaChange {\n  const type = dbCol.COLUMN_TYPE;\n  const nullable = dbCol.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n  const defaultValue = dbCol.COLUMN_DEFAULT;\n\n  let premigrationId: string | undefined;\n  if (nullable === \"NOT NULL\") {\n    premigrationId = uuid();\n    preMigrations[premigrationId] = {\n      tableName,\n      dbTable,\n      colName,\n      type,\n      migrationType: \"NEW_FIELD_NOT_NULL\",\n      defaultValue,\n    };\n  }\n\n  const defaultClause =\n    defaultValue === undefined || defaultValue === null\n      ? \"\"\n      : `DEFAULT ${buildDefault({ tableName, dbTable, colName, type, migrationType: \"INLINE\", defaultValue })}`;\n\n  return {\n    change: `ALTER TABLE \\`${tableName}\\` ADD COLUMN IF NOT EXISTS \\`${colName}\\` ${type} ${nullable} ${defaultClause};`,\n    premigrationId,\n  };\n}\n\n/** Builds a MODIFY COLUMN statement when a column's type/nullability/default changed. */\nfunction buildModifyColumnChange(\n  tableName: string,\n  dbTable: TableSchema,\n  colName: string,\n  dbCol: DatabaseColumn,\n  drizzleCol: DrizzleColumn,\n  preMigrations: Record<string, PreMigrationNotNull>,\n): SchemaChange | undefined {\n  const nullable = dbCol.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n  const dbIsNotNull = nullable === \"NOT NULL\";\n  const drizzleIsNotNull = drizzleCol.notNull;\n\n  const typeChanged =\n    normalizeMySQLType(dbCol.COLUMN_TYPE) !== normalizeMySQLType(drizzleCol.getSQLType());\n  const nullabilityChanged = dbIsNotNull !== drizzleIsNotNull;\n  const hasDrizzleDefault = drizzleCol.default !== null && drizzleCol.default !== undefined;\n  const hasDbDefault = dbCol.COLUMN_DEFAULT !== null && dbCol.COLUMN_DEFAULT !== undefined;\n  const defaultChanged =\n    hasDrizzleDefault && hasDbDefault && !drizzleCol.default?.includes(dbCol.COLUMN_DEFAULT);\n\n  if (!typeChanged && !nullabilityChanged && !defaultChanged) {\n    return undefined;\n  }\n\n  const type = dbCol.COLUMN_TYPE; // Use database type as source of truth\n  const defaultValue = dbCol.COLUMN_DEFAULT;\n\n  let premigrationId: string | undefined;\n  if (dbIsNotNull && !drizzleIsNotNull) {\n    premigrationId = uuid();\n    preMigrations[premigrationId] = {\n      tableName,\n      dbTable,\n      colName,\n      type,\n      migrationType: \"MODIFY_NOT_NULL\",\n      defaultValue,\n    };\n  }\n\n  const defaultClause =\n    defaultValue === undefined || defaultValue === null\n      ? \"\"\n      : ` DEFAULT ${buildDefault({ tableName, dbTable, colName, type, migrationType: \"INLINE\", defaultValue })}`;\n\n  return {\n    change: `ALTER TABLE \\`${tableName}\\` MODIFY COLUMN IF EXISTS \\`${colName}\\` ${type} ${nullable}${defaultClause};`,\n    premigrationId,\n  };\n}\n\n/** Diffs the columns of an existing table against its Drizzle definition. */\nfunction buildColumnChanges(\n  tableName: string,\n  dbTable: TableSchema,\n  drizzleColumns: Record<string, DrizzleColumn>,\n  preMigrations: Record<string, PreMigrationNotNull>,\n): SchemaChange[] {\n  const changes: SchemaChange[] = [];\n\n  for (const [colName, dbCol] of Object.entries(dbTable.columns)) {\n    const drizzleCol = Object.values(drizzleColumns).find((c) => c.name === colName);\n\n    if (!drizzleCol) {\n      changes.push(buildAddColumnChange(tableName, dbTable, colName, dbCol, preMigrations));\n      continue;\n    }\n\n    const change = buildModifyColumnChange(\n      tableName,\n      dbTable,\n      colName,\n      dbCol,\n      drizzleCol,\n      preMigrations,\n    );\n    if (change) {\n      changes.push(change);\n    }\n  }\n\n  return changes;\n}\n\n/** Diffs the indexes of an existing table against its Drizzle metadata. */\nfunction buildIndexChanges(\n  tableName: string,\n  dbTable: TableSchema,\n  metadata: TableMetadataInfo,\n): SchemaChange[] {\n  const changes: SchemaChange[] = [];\n\n  for (const [indexName, dbIndex] of Object.entries(dbTable.indexes)) {\n    if (indexName === \"PRIMARY\") {\n      continue;\n    }\n\n    const isForeignKeyIndex = metadata.foreignKeys.some(\n      (fk) => getForeignKeyName(fk) === indexName || compareForeignKey(fk, dbIndex),\n    );\n    if (isForeignKeyIndex) {\n      continue;\n    }\n\n    const existsUniqIndex = metadata.uniqueConstraints.find(\n      (uc) => getUniqueConstraintName(uc) === indexName,\n    );\n    let drizzleIndex = metadata.indexes.find((i) => getIndexName(i) === indexName);\n    if (!drizzleIndex && existsUniqIndex) {\n      drizzleIndex = existsUniqIndex as unknown as AnyIndexBuilder;\n    }\n\n    const cols = dbIndex.columns.map((col) => `\\`${col}\\``).join(\", \");\n    const unique = dbIndex.unique ? \"UNIQUE \" : \"\";\n\n    if (!drizzleIndex) {\n      changes.push({\n        change: `CREATE ${unique}INDEX if not exists \\`${indexName}\\` ON \\`${tableName}\\` (${cols});`,\n      });\n      continue;\n    }\n\n    const columnsChanged = dbIndex.columns.join(\", \") !== getIndexColumns(drizzleIndex).join(\", \");\n    const uniqueChanged = dbIndex.unique !== drizzleIndex instanceof UniqueConstraintBuilder;\n    if (columnsChanged || uniqueChanged) {\n      changes.push(\n        { change: `DROP INDEX \\`${indexName}\\` ON \\`${tableName}\\`;` },\n        {\n          change: `CREATE  ${unique}INDEX if not exists \\`${indexName}\\` ON \\`${tableName}\\` (${cols});`,\n        },\n      );\n    }\n  }\n\n  return changes;\n}\n\n/** Diffs the foreign keys of an existing table against its Drizzle metadata. */\nfunction buildForeignKeyChanges(\n  tableName: string,\n  dbTable: TableSchema,\n  metadata: TableMetadataInfo,\n): SchemaChange[] {\n  const changes: SchemaChange[] = [];\n\n  // Foreign keys present in the database but not in the schema\n  for (const [fkName, dbFK] of Object.entries(dbTable.foreignKeys)) {\n    const drizzleFK = metadata.foreignKeys.find(\n      (fk) =>\n        getForeignKeyName(fk) === fkName ||\n        compareForeignKey(fk, { columns: [dbFK.column], unique: false }),\n    );\n    if (!drizzleFK) {\n      changes.push({\n        change: `ALTER TABLE \\`${tableName}\\` ADD CONSTRAINT \\`${fkName}\\` FOREIGN KEY (\\`${dbFK.column}\\`) REFERENCES \\`${dbFK.referencedTable}\\` (\\`${dbFK.referencedColumn}\\`);`,\n      });\n    }\n  }\n\n  // Foreign keys present in the schema but not in the database\n  for (const drizzleForeignKey of metadata.foreignKeys) {\n    const isDbFk = Object.keys(dbTable.foreignKeys).some((fk) => {\n      const foreignKey = dbTable.foreignKeys[fk];\n      return (\n        fk === getForeignKeyName(drizzleForeignKey) ||\n        compareForeignKey(drizzleForeignKey, { columns: [foreignKey.column], unique: false })\n      );\n    });\n    if (isDbFk) {\n      continue;\n    }\n\n    const fkName = getForeignKeyName(drizzleForeignKey);\n    if (fkName) {\n      changes.push({ change: `ALTER TABLE \\`${tableName}\\` DROP FOREIGN KEY  \\`${fkName}\\`;` });\n    } else {\n      // @ts-ignore - Internal property access\n      const columns = drizzleForeignKey.columns as { name: string }[] | undefined;\n      const columnNames = columns?.length\n        ? columns.map((c) => c.name).join(\", \")\n        : \"unknown columns\";\n      console.warn(\n        `⚠️ Drizzle model for table '${tableName}' does not provide a name for FOREIGN KEY constraint on columns: ${columnNames}`,\n      );\n    }\n  }\n\n  return changes;\n}\n\n/**\n * Generates SQL changes by comparing Drizzle schema with database schema\n * @param drizzleSchema - Schema from Drizzle\n * @param dbSchema - Schema from database\n * @param schemaModule - Drizzle schema module\n * @returns Array of SQL statements\n */\nfunction generateSchemaChanges(\n  drizzleSchema: DrizzleSchema,\n  dbSchema: DatabaseSchema,\n  schemaModule: Record<string, AnyMySqlTable>,\n): {\n  changes: SchemaChange[];\n  preMigrations: Record<string, PreMigrationNotNull>;\n} {\n  const changes: SchemaChange[] = [];\n  const preMigrations: Record<string, PreMigrationNotNull> = {};\n\n  for (const [tableName, dbTable] of Object.entries(dbSchema)) {\n    const drizzleColumns = drizzleSchema[tableName];\n\n    // Table exists in the database but not in the schema - create it wholesale.\n    if (!drizzleColumns) {\n      changes.push(...buildNewTableChanges(tableName, dbTable));\n      continue;\n    }\n\n    // Otherwise diff columns, then indexes and foreign keys (when the table is known).\n    changes.push(...buildColumnChanges(tableName, dbTable, drizzleColumns, preMigrations));\n\n    const table = Object.values(schemaModule).find(\n      (t) => getTableMetadata(t).tableName === tableName,\n    );\n    if (table) {\n      const metadata = getTableMetadata(table);\n      changes.push(\n        ...buildIndexChanges(tableName, dbTable, metadata),\n        ...buildForeignKeyChanges(tableName, dbTable, metadata),\n      );\n    }\n  }\n\n  return { changes, preMigrations };\n}\n\n/**\n * Updates an existing database migration by generating schema modifications.\n * @param options - Database connection settings and output paths.\n */\nexport const updateMigration = async (options: UpdateMigrationOptions) => {\n  try {\n    let version = await loadMigrationVersion(options.output);\n    const prevVersion = version;\n\n    if (version < 1) {\n      console.log(\n        `⚠️ Initial migration not found. Run \"npx forge-sql-orm migrations:create\" first.`,\n      );\n      process.exit(0);\n    }\n    version += 1;\n\n    // Create database connection\n    const connection = await mysql.createConnection({\n      host: options.host,\n      port: options.port,\n      user: options.user,\n      password: options.password,\n      database: options.dbName,\n    });\n\n    try {\n      // Get current database schema\n      const dbSchema = await getDatabaseSchema(connection, options.dbName);\n\n      // Import Drizzle schema using absolute path\n      const schemaPath = path.resolve(options.entitiesPath, \"schema.ts\");\n      if (!fs.existsSync(schemaPath)) {\n        throw new Error(`Schema file not found at: ${schemaPath}`);\n      }\n\n      const schemaModule = await import(schemaPath);\n      if (!schemaModule) {\n        throw new Error(`Invalid schema file at: ${schemaPath}. Schema must export tables.`);\n      }\n\n      // Process exported tables\n      const drizzleSchema: DrizzleSchema = {};\n\n      // Get all exports that are tables\n      const tables = Object.values(schemaModule) as MySqlTable<TableConfig>[];\n\n      tables.forEach((table) => {\n        const metadata = getTableMetadata(table);\n        if (metadata.tableName) {\n          // Convert AnyColumn to DrizzleColumn\n          const columns: Record<string, DrizzleColumn> = {};\n          Object.entries(metadata.columns).forEach(([name, column]) => {\n            columns[name] = {\n              type: column.dataType,\n              notNull: column.notNull,\n              autoincrement: (column as { autoIncrement?: boolean }).autoIncrement,\n              columnType: column.columnType,\n              name: column.name,\n              default: (() => {\n                if (!column.hasDefault) {\n                  return undefined;\n                }\n\n                const defaultValue = column.default;\n\n                // If default is an object with toQuery method (e.g., SQL expression)\n                if (isToQueryable(defaultValue)) {\n                  return defaultValue.toQuery({}).sql;\n                }\n\n                // Otherwise, convert to string\n                return String(defaultValue);\n              })(),\n              getSQLType: () => column.getSQLType(),\n            };\n          });\n          drizzleSchema[metadata.tableName] = columns;\n        }\n      });\n\n      if (Object.keys(drizzleSchema).length === 0) {\n        throw new Error(`No valid tables found in schema at: ${schemaPath}`);\n      }\n\n      console.log(\"Found tables:\", Object.keys(drizzleSchema));\n\n      // Generate SQL changes\n      const createStatements = filterWithPreviousMigration(\n        generateSchemaChanges(drizzleSchema, dbSchema, schemaModule),\n        prevVersion,\n        options.output,\n      );\n\n      if (createStatements.changes.length) {\n        // Generate migration file content\n        const migrationFile = generateMigrationFile(createStatements, version);\n\n        // Save migration files only if there are actual changes\n        if (saveMigrationFiles(migrationFile, version, options.output)) {\n          console.log(`✅ Migration successfully updated!`);\n        }\n        process.exit(0);\n      } else {\n        console.log(`⚠️ No new migration changes detected.`);\n        process.exit(0);\n      }\n    } finally {\n      await connection.end();\n    }\n  } catch (error) {\n    console.error(`❌ Error during migration update:`, error);\n    process.exit(1);\n  }\n};\n","// SPDX-FileCopyrightText: 2025-2026 Vasyl Zakharchenko\n// SPDX-License-Identifier: MIT\n\nimport \"reflect-metadata\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { MySqlTable, TableConfig } from \"drizzle-orm/mysql-core\";\nimport { getTableMetadata, generateDropTableStatements } from \"forge-sql-orm\";\n\n/**\n * Options for dropping all tables.\n */\nexport interface DropMigrationOptions {\n  entitiesPath: string;\n  output: string;\n}\n\n/**\n * Generates a migration ID using current date\n * @returns Migration ID string with current date\n */\nfunction generateMigrationUUID(version: number): string {\n  const now = new Date();\n  const timestamp = now.getTime();\n  return `MIGRATION_V${version}_${timestamp}`;\n}\n\n/**\n * Generates a migration file using the provided SQL statements.\n * @param createStatements - Array of SQL statements.\n * @param version - Migration version number.\n * @returns TypeScript migration file content.\n */\nfunction generateMigrationFile(createStatements: string[], version: number): string {\n  const uniqId = generateMigrationUUID(version);\n  // Clean each SQL statement and generate migration lines with .enqueue()\n  const migrationLines = createStatements\n    .map(\n      (stmt, index) => `        .enqueue(\"${uniqId}_${index}\", \\\"${stmt}\\\")`, // eslint-disable-line no-useless-escape\n    )\n    .join(\"\\n\");\n\n  // Migration template\n  return `import { MigrationRunner } from \"@forge/sql/out/migration\";\n\nexport default (migrationRunner: MigrationRunner): MigrationRunner => {\n    return migrationRunner\n${migrationLines};\n};`;\n}\n\n/**\n * Saves the generated migration file along with `migrationCount.ts` and `index.ts`.\n * @param migrationCode - The migration code to be written to the file.\n * @param version - Migration version number.\n * @param outputDir - Directory where the migration files will be saved.\n */\nfunction saveMigrationFiles(migrationCode: string, version: number, outputDir: string) {\n  if (!fs.existsSync(outputDir)) {\n    fs.mkdirSync(outputDir, { recursive: true });\n  }\n\n  const migrationFilePath = path.join(outputDir, `migrationV${version}.ts`);\n  const migrationCountPath = path.join(outputDir, `migrationCount.ts`);\n  const indexFilePath = path.join(outputDir, `index.ts`);\n\n  // Write the migration file\n  fs.writeFileSync(migrationFilePath, migrationCode);\n\n  // Write the migration count file\n  fs.writeFileSync(migrationCountPath, `export const MIGRATION_VERSION = ${version};`);\n\n  // Generate the migration index file\n  const indexFileContent = `import { MigrationRunner } from \"@forge/sql/out/migration\";\nimport { MIGRATION_VERSION } from \"./migrationCount\";\n\nexport type MigrationType = (\n  migrationRunner: MigrationRunner,\n) => MigrationRunner;\n\nexport default async (\n  migrationRunner: MigrationRunner,\n): Promise<MigrationRunner> => {\n  for (let i = 1; i <= MIGRATION_VERSION; i++) {\n    const migrations = (await import(\\`./migrationV\\${i}\\`)) as {\n      default: MigrationType;\n    };\n    migrations.default(migrationRunner);\n  }\n  return migrationRunner;\n};`;\n\n  fs.writeFileSync(indexFilePath, indexFileContent);\n\n  console.log(`✅ Migration file created: ${migrationFilePath}`);\n  console.log(`✅ Migration count file updated: ${migrationCountPath}`);\n  console.log(`✅ Migration index file created: ${indexFilePath}`);\n}\n\n/**\n * Creates a full database migration.\n * @param options - Database connection settings and output paths.\n */\nexport const dropMigration = async (options: DropMigrationOptions) => {\n  try {\n    // Start from version 1 if no previous migrations exist\n    const version = 1;\n\n    // Import Drizzle schema using absolute path\n    const schemaPath = path.resolve(options.entitiesPath, \"schema.ts\");\n    if (!fs.existsSync(schemaPath)) {\n      throw new Error(`Schema file not found at: ${schemaPath}`);\n    }\n\n    const schemaModule = await import(schemaPath);\n    if (!schemaModule) {\n      throw new Error(`Invalid schema file at: ${schemaPath}. Schema must export tables.`);\n    }\n\n    // Get all exports that are tables\n    const tables = Object.values(schemaModule) as MySqlTable<TableConfig>[];\n\n    if (tables.length === 0) {\n      throw new Error(`No valid tables found in schema at: ${schemaPath}`);\n    }\n\n    // Get table names for logging\n    const tableNames = tables\n      .map((table) => {\n        const metadata = getTableMetadata(table);\n        return metadata.tableName;\n      })\n      .filter(Boolean);\n\n    console.log(\"Found tables:\", tableNames);\n\n    // Generate drop statements\n    const dropStatements = generateDropTableStatements(tableNames);\n\n    // Generate and save migration files\n    const migrationFile = generateMigrationFile(dropStatements, version);\n    saveMigrationFiles(migrationFile, version, options.output);\n\n    console.log(`✅ Migration successfully created!`);\n    process.exit(0);\n  } catch (error) {\n    console.error(`❌ Error during migration creation:`, error);\n    process.exit(1);\n  }\n};\n","// SPDX-FileCopyrightText: 2025-2026 Vasyl Zakharchenko\n// SPDX-License-Identifier: MIT\n\nimport \"reflect-metadata\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { execSync } from \"node:child_process\";\n\n/**\n * Options for direct schema creation from Drizzle models.\n */\nexport interface CreateSchemaOptions {\n  host?: string;\n  port?: number;\n  user?: string;\n  password?: string;\n  dbName?: string;\n  entitiesPath: string;\n}\n\n/**\n * Creates/updates DB schema directly from Drizzle models.\n * Uses drizzle-kit push to apply DDL immediately.\n */\nexport const createSchema = async (options: CreateSchemaOptions) => {\n  try {\n    if (!options.host || !options.port || !options.user || !options.password || !options.dbName) {\n      console.error(\n        \"❌ Error: Database connection parameters are required (host, port, user, password, dbName)\",\n      );\n      process.exit(1);\n    }\n\n    const schemaPath = path.resolve(options.entitiesPath, \"schema.ts\");\n    if (!fs.existsSync(schemaPath)) {\n      throw new Error(`Schema file not found at: ${schemaPath}`);\n    }\n\n    const encodedUser = encodeURIComponent(options.user);\n    const encodedPassword = encodeURIComponent(options.password);\n    const encodedHost = encodeURIComponent(options.host);\n    const encodedDbName = encodeURIComponent(options.dbName);\n\n    const dbUrl = `mysql://${encodedUser}:${encodedPassword}@${encodedHost}:${options.port}/${encodedDbName}`;\n\n    console.log(`📦 Applying schema from: ${schemaPath}`);\n    console.log(`🗄️  Target database: ${options.dbName} (${options.host}:${options.port})`);\n\n    execSync(`npx drizzle-kit push --dialect mysql --schema \"${schemaPath}\" --url \"${dbUrl}\"`, {\n      stdio: \"inherit\",\n    });\n\n    console.log(\"✅ Schema successfully applied from Drizzle models.\");\n    process.exit(0);\n  } catch (error) {\n    console.error(\"❌ Error during schema creation:\", error);\n    process.exit(1);\n  }\n};\n","#!/usr/bin/env node\n// SPDX-FileCopyrightText: 2025-2026 Vasyl Zakharchenko\n// SPDX-License-Identifier: MIT\n\nimport { Command } from \"commander\";\nimport dotenv from \"dotenv\";\nimport inquirer from \"inquirer\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { generateModels, type GenerateModelsOptions } from \"./actions/generate-models\";\nimport { createMigration, type CreateMigrationOptions } from \"./actions/migrations-create\";\nimport { updateMigration, type UpdateMigrationOptions } from \"./actions/migrations-update\";\nimport { dropMigration, type DropMigrationOptions } from \"./actions/migrations-drops\";\nimport { createSchema, type CreateSchemaOptions } from \"./actions/schema-create\";\n\nconst ENV_PATH = path.resolve(process.cwd(), \".env\");\n// 🔄 Load environment variables from `.env` file\ndotenv.config({ path: ENV_PATH });\n\n/**\n * Resolved configuration shared across all CLI commands.\n */\ninterface CliConfig {\n  host?: string;\n  port?: number;\n  user?: string;\n  password?: string;\n  dbName?: string;\n  output?: string;\n  versionField?: string;\n  entitiesPath?: string;\n  force?: boolean;\n}\n\n/**\n * Raw options object provided by Commander to each command action.\n * All values arrive as strings (or booleans for flags) from the CLI.\n */\ninterface CommandOptions {\n  host?: string;\n  port?: string;\n  user?: string;\n  password?: string;\n  dbName?: string;\n  output?: string;\n  versionField?: string;\n  entitiesPath?: string;\n  force?: boolean;\n  saveEnv?: boolean;\n}\n\n/**\n * Raw answers returned by Inquirer. Every prompted value is a string,\n * including `port`, which is converted to a number before it reaches `CliConfig`.\n */\ninterface PromptAnswers {\n  host?: string;\n  port?: string;\n  user?: string;\n  password?: string;\n  dbName?: string;\n  output?: string;\n  versionField?: string;\n  entitiesPath?: string;\n}\n\nconst saveEnvFile = (config: CliConfig) => {\n  let envContent = \"\";\n  const envFilePath = ENV_PATH;\n\n  if (fs.existsSync(envFilePath)) {\n    envContent = fs.readFileSync(envFilePath, \"utf8\");\n  }\n\n  const envVars = envContent\n    .split(\"\\n\")\n    .filter((line) => line.trim() !== \"\" && !line.startsWith(\"#\"))\n    .reduce<Record<string, string>>((acc, line) => {\n      const [key, ...value] = line.split(\"=\");\n      acc[key] = value.join(\"=\");\n      return acc;\n    }, {});\n\n  Object.entries(config).forEach(([key, value]) => {\n    envVars[`FORGE_SQL_ORM_${key.toUpperCase()}`] = String(value);\n  });\n\n  const updatedEnvContent = Object.entries(envVars)\n    .map(([key, value]) => `${key}=${value}`)\n    .join(\"\\n\");\n\n  fs.writeFileSync(envFilePath, updatedEnvContent, { encoding: \"utf8\" });\n\n  console.log(\"✅ Configuration saved to .env without overwriting other variables.\");\n};\n\n/**\n * Prompts the user for missing parameters using Inquirer.js.\n * @param config - The current configuration object.\n * @param defaultOutput - Default output path.\n * @param customAskMissingParams - Optional function for additional prompts.\n * @returns Updated configuration with user input.\n */\nconst askMissingParams = async (\n  config: CliConfig,\n  defaultOutput: string,\n  customAskMissingParams?: (cfg: CliConfig, questions: unknown[]) => void,\n): Promise<CliConfig> => {\n  const questions: unknown[] = [];\n\n  if (!config.host)\n    questions.push({\n      type: \"input\",\n      name: \"host\",\n      message: \"Enter database host:\",\n      default: \"localhost\",\n    });\n\n  if (!config.port)\n    questions.push({\n      type: \"input\",\n      name: \"port\",\n      message: \"Enter database port:\",\n      default: \"3306\",\n      validate: (input: string) => !Number.isNaN(Number.parseInt(input, 10)),\n    });\n\n  if (!config.user)\n    questions.push({\n      type: \"input\",\n      name: \"user\",\n      message: \"Enter database user:\",\n      default: \"root\",\n    });\n\n  if (!config.password)\n    questions.push({\n      type: \"password\",\n      name: \"password\",\n      message: \"Enter database password:\",\n      mask: \"*\",\n    });\n\n  if (!config.dbName)\n    questions.push({\n      type: \"input\",\n      name: \"dbName\",\n      message: \"Enter database name:\",\n    });\n\n  if (!config.output)\n    questions.push({\n      type: \"input\",\n      name: \"output\",\n      message: \"Enter output path:\",\n      default: defaultOutput,\n    });\n\n  // Allow additional questions from the caller\n  if (customAskMissingParams) {\n    customAskMissingParams(config, questions);\n  }\n\n  // If there are missing parameters, prompt the user\n  if (questions.length > 0) {\n    // @ts-ignore - Ignore TypeScript warning for dynamic question type\n    const answers = (await inquirer.prompt(questions)) as PromptAnswers;\n    const rawPort = config.port ?? answers.port;\n    return {\n      ...config,\n      ...answers,\n      port: rawPort === undefined ? undefined : Number.parseInt(String(rawPort), 10),\n    };\n  }\n\n  return config;\n};\n\n/**\n * Retrieves configuration parameters from command-line arguments and environment variables.\n * If any required parameters are missing, prompts the user for input.\n * @param cmd - The command object containing CLI options.\n * @param defaultOutput - Default output directory.\n * @param customConfig - Optional function for additional configuration parameters.\n * @param customAskMissingParams - Optional function for additional prompts.\n * @returns A fully resolved configuration object.\n */\n/**\n * Resolves the database port from the CLI flag, falling back to the environment.\n * @param cmdPort - Raw `--port` value from the command line.\n * @returns The parsed port number, or undefined when neither source is set.\n */\nfunction resolvePort(cmdPort?: string): number | undefined {\n  const raw = cmdPort ?? process.env.FORGE_SQL_ORM_PORT;\n  return raw === undefined ? undefined : Number.parseInt(raw, 10);\n}\n\nconst getConfig = async (\n  cmd: CommandOptions,\n  defaultOutput: string,\n  customConfig?: () => Partial<CliConfig>,\n  customAskMissingParams?: (cfg: CliConfig, questions: unknown[]) => void,\n): Promise<CliConfig> => {\n  let config = {\n    host: cmd.host || process.env.FORGE_SQL_ORM_HOST,\n    port: resolvePort(cmd.port),\n    user: cmd.user || process.env.FORGE_SQL_ORM_USER,\n    password: cmd.password || process.env.FORGE_SQL_ORM_PASSWORD,\n    dbName: cmd.dbName || process.env.FORGE_SQL_ORM_DBNAME,\n    output: cmd.output || process.env.FORGE_SQL_ORM_OUTPUT,\n  };\n\n  // Merge additional configurations if provided\n  if (customConfig) {\n    config = { ...config, ...customConfig() };\n  }\n\n  const conf = await askMissingParams(config, defaultOutput, customAskMissingParams);\n  if (cmd.saveEnv) {\n    saveEnvFile(conf);\n  }\n  return conf;\n};\n\n// 📌 Initialize CLI\nexport const program = new Command();\nprogram.version(\"1.0.0\");\n\n// ✅ Command: Generate database models (Entities)\nprogram\n  .command(\"generate:model\")\n  .description(\"Generate Drizzle models from the database.\")\n  .option(\"--host <string>\", \"Database host\")\n  .option(\"--port <number>\", \"Database port\")\n  .option(\"--user <string>\", \"Database user\")\n  .option(\"--password <string>\", \"Database password\")\n  .option(\"--dbName <string>\", \"Database name\")\n  .option(\"--output <string>\", \"Output path for entities\")\n  .option(\"--versionField <string>\", \"Field name for versioning\")\n  .option(\"--saveEnv\", \"Save configuration to .env file\")\n  .action(async (cmd) => {\n    const config = await getConfig(\n      cmd,\n      \"./database/entities\",\n      () => ({\n        versionField: cmd.versionField || process.env.FORGE_SQL_ORM_VERSIONFIELD,\n      }),\n      (cfg, questions: unknown[]) => {\n        if (!cfg.versionField) {\n          questions.push({\n            type: \"input\",\n            name: \"versionField\",\n            message: \"Enter the field name for versioning (leave empty to skip):\",\n            default: \"\",\n          });\n        }\n      },\n    );\n    await generateModels(config as GenerateModelsOptions);\n  });\n\n// ✅ Command: Create initial database migration\nprogram\n  .command(\"migrations:create\")\n  .description(\"Generate an initial migration for the entire database.\")\n  .option(\"--host <string>\", \"Database host\")\n  .option(\"--port <number>\", \"Database port\")\n  .option(\"--user <string>\", \"Database user\")\n  .option(\"--password <string>\", \"Database password\")\n  .option(\"--dbName <string>\", \"Database name\")\n  .option(\"--output <string>\", \"Output path for migrations\")\n  .option(\"--force\", \"Force creation even if migrations exist\")\n  .option(\"--saveEnv\", \"Save configuration to .env file\")\n  .action(async (cmd) => {\n    const config = await getConfig(cmd, \"./database/migration\", () => ({\n      force: cmd.force || false,\n    }));\n    await createMigration(config as CreateMigrationOptions);\n  });\n\n// ✅ Command: Update migration for schema changes\nprogram\n  .command(\"migrations:update\")\n  .description(\"Generate a migration to update the database schema.\")\n  .option(\"--host <string>\", \"Database host\")\n  .option(\"--port <number>\", \"Database port\")\n  .option(\"--user <string>\", \"Database user\")\n  .option(\"--password <string>\", \"Database password\")\n  .option(\"--dbName <string>\", \"Database name\")\n  .option(\"--output <string>\", \"Output path for migrations\")\n  .option(\"--entitiesPath <string>\", \"Path to the folder containing entities\")\n  .option(\"--saveEnv\", \"Save configuration to .env file\")\n  .action(async (cmd) => {\n    const config = await getConfig(\n      cmd,\n      \"./database/migration\",\n      () => ({\n        entitiesPath: cmd.entitiesPath || process.env.FORGE_SQL_ORM_ENTITIESPATH,\n      }),\n      (cfg, questions: unknown[]) => {\n        if (!cfg.entitiesPath)\n          questions.push({\n            type: \"input\",\n            name: \"entitiesPath\",\n            message: \"Enter the path to entities:\",\n            default: \"./database/entities\",\n          });\n      },\n    );\n    await updateMigration(config as UpdateMigrationOptions);\n  });\n\n// ✅ Command: Drop all migrations\nprogram\n  .command(\"migrations:drop\")\n  .description(\"Generate a migration to drop all tables and clear migrations history.\")\n  .option(\"--host <string>\", \"Database host\")\n  .option(\"--port <number>\", \"Database port\")\n  .option(\"--user <string>\", \"Database user\")\n  .option(\"--password <string>\", \"Database password\")\n  .option(\"--dbName <string>\", \"Database name\")\n  .option(\"--output <string>\", \"Output path for migrations\")\n  .option(\"--entitiesPath <string>\", \"Path to the folder containing entities\")\n  .option(\"--saveEnv\", \"Save configuration to .env file\")\n  .action(async (cmd) => {\n    const config = await getConfig(\n      cmd,\n      \"./database/migration\",\n      () => ({\n        entitiesPath: cmd.entitiesPath || process.env.FORGE_SQL_ORM_ENTITIESPATH,\n      }),\n      (cfg, questions: unknown[]) => {\n        if (!cfg.entitiesPath)\n          questions.push({\n            type: \"input\",\n            name: \"entitiesPath\",\n            message: \"Enter the path to entities:\",\n            default: \"./database/entities\",\n          });\n      },\n    );\n    await dropMigration(config as DropMigrationOptions);\n  });\n\n// ✅ Command: Apply DB schema directly from Drizzle models\nprogram\n  .command(\"schema:create\")\n  .description(\"Create/update database schema directly from Drizzle models.\")\n  .option(\"--host <string>\", \"Database host\")\n  .option(\"--port <number>\", \"Database port\")\n  .option(\"--user <string>\", \"Database user\")\n  .option(\"--password <string>\", \"Database password\")\n  .option(\"--dbName <string>\", \"Database name\")\n  .option(\"--entitiesPath <string>\", \"Path to the folder containing entities\")\n  .option(\"--saveEnv\", \"Save configuration to .env file\")\n  .action(async (cmd) => {\n    const config = await getConfig(\n      cmd,\n      \"./database/entities\",\n      () => ({\n        entitiesPath: cmd.entitiesPath || process.env.FORGE_SQL_ORM_ENTITIESPATH,\n      }),\n      (cfg, questions: unknown[]) => {\n        if (!cfg.entitiesPath)\n          questions.push({\n            type: \"input\",\n            name: \"entitiesPath\",\n            message: \"Enter the path to entities:\",\n            default: \"./database/entities\",\n          });\n      },\n    );\n    await createSchema(config as CreateSchemaOptions);\n  });\n\n// 🔥 Execute CLI\nprogram.parse(process.argv);\n"],"mappings":"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"}