forge-sql-orm-cli 2.1.18 → 2.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cli/cli.js +1 -1
- package/dist-cli/cli.js.map +1 -1
- package/dist-cli/cli.mjs +1 -1
- package/dist-cli/cli.mjs.map +1 -1
- package/package.json +1 -1
- package/src/actions/migrations-update.ts +1 -1
package/dist-cli/cli.js
CHANGED
|
@@ -786,7 +786,7 @@ const updateMigration = async (options) => {
|
|
|
786
786
|
autoincrement: column.autoincrement,
|
|
787
787
|
columnType: column.columnType,
|
|
788
788
|
name: column.name,
|
|
789
|
-
default:
|
|
789
|
+
default: column.hasDefault ? String(column.default) : void 0,
|
|
790
790
|
getSQLType: () => column.getSQLType()
|
|
791
791
|
};
|
|
792
792
|
});
|
package/dist-cli/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../src/actions/generate-models.ts","../src/actions/migrations-create.ts","../src/actions/migrations-update.ts","../src/actions/migrations-drops.ts","../src/cli.ts"],"sourcesContent":["import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { execSync } from \"child_process\";\n\n/**\n * Options for model generation\n */\ninterface 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, any>;\n foreignKeys: Record<string, any>;\n uniqueConstraints: Record<string, any>;\n checkConstraint: Record<string, any>;\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/**\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 await 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 // Process metadata to create version map\n const metaDir = path.join(options.output, \"meta\");\n const additionalMetadata: AdditionalMetadata = {};\n\n if (fs.existsSync(metaDir)) {\n const snapshotFile = path.join(metaDir, \"0000_snapshot.json\");\n if (fs.existsSync(snapshotFile)) {\n const snapshotData = JSON.parse(fs.readFileSync(snapshotFile, \"utf-8\"));\n\n // Process each table from the snapshot\n for (const [tableName, tableData] of Object.entries(snapshotData.tables)) {\n const table = tableData as TableMetadata;\n\n // Check if table name starts with 'a_' and warn about cache\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 // Find version field in columns\n const versionField = Object.entries(table.columns).find(\n ([_, col]) => col.name.toLowerCase() === options.versionField,\n );\n\n if (versionField) {\n const [_, col] = versionField;\n const fieldType = col.type;\n const isSupportedType =\n fieldType === \"datetime\" ||\n fieldType === \"timestamp\" ||\n fieldType === \"int\" ||\n fieldType === \"number\" ||\n fieldType === \"decimal\";\n if (!col.notNull) {\n console.warn(\n `Version field \"${col.name}\" in table ${tableName} is nullable. Versioning may not work correctly.`,\n );\n } else if (!isSupportedType) {\n console.warn(\n `Version field \"${col.name}\" in table ${tableName} has unsupported type \"${fieldType}\". ` +\n `Only datetime, timestamp, int, and decimal types are supported for versioning. Versioning will be skipped.`,\n );\n } else {\n additionalMetadata[tableName] = {\n tableName,\n versionField: {\n fieldName: col.name,\n },\n };\n }\n }\n }\n }\n }\n\n // Create version metadata file\n const versionMetadataContent = `/**\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 fs.writeFileSync(path.join(options.output, \"index.ts\"), versionMetadataContent);\n\n // Replace MySQL types in the generated schema file\n const schemaPath = path.join(options.output, \"schema.ts\");\n if (fs.existsSync(schemaPath)) {\n const schemaContent = fs.readFileSync(schemaPath, \"utf-8\");\n const modifiedContent = replaceMySQLTypes(schemaContent);\n fs.writeFileSync(schemaPath, modifiedContent);\n console.log(`✅ Updated schema types in: ${schemaPath}`);\n }\n\n // Remove migration files and meta directory if they exist\n const migrationDir = path.join(options.output, \"migrations\");\n\n if (fs.existsSync(migrationDir)) {\n fs.rmSync(migrationDir, { recursive: true, force: true });\n console.log(`✅ Removed: ${migrationDir}`);\n }\n\n // Read journal and remove corresponding SQL file\n if (fs.existsSync(metaDir)) {\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\n // Remove SQL files for each entry\n for (const entry of journalData.entries) {\n const sqlFile = path.join(options.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 // Remove meta directory after processing\n fs.rmSync(metaDir, { recursive: true, force: true });\n console.log(`✅ Removed: ${metaDir}`);\n }\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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"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<any[]>(\"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 const result = rows as CreateTableRow[];\n if (result.length > 0 && result[0][\"Create Table\"]) {\n return result[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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport mysql from \"mysql2/promise\";\nimport { 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\ninterface DrizzleColumn {\n type: string;\n notNull: boolean;\n autoincrement?: boolean;\n columnType?: any;\n name: string;\n default?: string;\n getSQLType: () => string;\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 =\n preMigration.defaultValue === undefined || preMigration.defaultValue === null\n ? \"?\"\n : 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\n const updateStatement = generateUpdateStatement(preMigration, defaultValue);\n migrationLineList.push(\n `\\nmigrationRunner.enqueue(\"${versionPrefix}${index}_UPDATE_EXISTS_RECORDS\", \"${updateStatement}\")`,\n );\n\n // Step 3: Apply the MODIFY statement\n migrationLineList.push(\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/**\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\n const prevStatements = prevContent\n .split(\"\\n\")\n .filter((line) => line.includes(\".enqueue(\"))\n .map((line) => {\n const match = line.match(/\\.enqueue\\([^,]+,\\s*\"([^\"]+)\"/);\n return match ? match[1].replace(/\\s+/g, \" \").trim() : \"\";\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.includes(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\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 fcolumns.sort().join(\",\") === columns.sort().join(\",\");\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, any>,\n): {\n changes: { change: string; premigrationId?: string }[];\n preMigrations: Record<string, PreMigrationNotNull>;\n} {\n const changes: { change: string; premigrationId?: string }[] = [];\n const preMigrations: Record<string, PreMigrationNotNull> = {};\n // First check existing tables in database\n for (const [tableName, dbTable] of Object.entries(dbSchema)) {\n const drizzleColumns = drizzleSchema[tableName];\n\n if (!drizzleColumns) {\n // Table exists in database but not in schema - create it\n const columns = Object.entries(dbTable.columns)\n .map(([colName, col]) => {\n const type = col.COLUMN_TYPE;\n const nullable = col.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n const autoIncrement = col.EXTRA.includes(\"auto_increment\") ? \"AUTO_INCREMENT\" : \"\";\n return `\\`${colName}\\` ${type} ${nullable} ${autoIncrement}`.trim();\n })\n .join(\",\\n \");\n\n changes.push({ change: `CREATE TABLE if not exists \\`${tableName}\\` (\\n ${columns}\\n);` });\n\n // Create indexes for new table\n for (const [indexName, dbIndex] of Object.entries(dbTable.indexes)) {\n // Skip primary key and foreign key indexes\n if (indexName === \"PRIMARY\") {\n continue;\n }\n\n // Check if any column in this index is a foreign key\n const isForeignKeyIndex = dbIndex.columns.some((colName) => {\n const column = dbTable.columns[colName];\n return column && column.COLUMN_KEY === \"MUL\" && column.EXTRA.includes(\"foreign key\");\n });\n\n if (isForeignKeyIndex) {\n continue;\n }\n\n // Create index\n const columns = 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}\\` (${columns});`,\n });\n }\n\n // Create foreign keys for new table\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 continue;\n }\n\n // Check for column changes in existing tables\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 // Column exists in database but not in schema - create it\n const type = dbCol.COLUMN_TYPE;\n const nullable = dbCol.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n let premigrationId = nullable === \"NOT NULL\" ? uuid() : undefined;\n const defaultValue = dbCol.COLUMN_DEFAULT;\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 changes.push({\n change: `ALTER TABLE \\`${tableName}\\` ADD COLUMN IF NOT EXISTS \\`${colName}\\` ${type} ${nullable} ${\n defaultValue === undefined || defaultValue === null\n ? \"\"\n : `DEFAULT ${buildDefault({\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"INLINE\",\n defaultValue: defaultValue,\n })}`\n };`,\n premigrationId,\n });\n continue;\n }\n\n // Check for column changes (type, nullability, or default value)\n const normalizedDbType = normalizeMySQLType(dbCol.COLUMN_TYPE);\n const normalizedDrizzleType = normalizeMySQLType(drizzleCol.getSQLType());\n const nullable = dbCol.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n const dbIsNotNull = nullable === \"NOT NULL\";\n const drizzleIsNotNull = drizzleCol.notNull;\n\n // Check if type has changed\n const typeChanged = normalizedDbType !== normalizedDrizzleType;\n\n // Check if nullability has changed\n const nullabilityChanged = dbIsNotNull !== drizzleIsNotNull;\n\n // Check if default value has changed\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 !== dbCol.COLUMN_DEFAULT;\n\n // Column needs modification if any of these changed\n if (typeChanged || nullabilityChanged || defaultChanged) {\n const type = dbCol.COLUMN_TYPE; // Use database type as source of truth\n const defaultValue = dbCol.COLUMN_DEFAULT;\n\n // Determine if we need a pre-migration for NOT NULL constraint\n let premigrationId: string | undefined = undefined;\n if (dbIsNotNull && !drizzleIsNotNull) {\n // Changing from NULL to NOT NULL - need pre-migration\n premigrationId = uuid();\n preMigrations[premigrationId] = {\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"MODIFY_NOT_NULL\",\n defaultValue: defaultValue,\n };\n }\n\n // Build DEFAULT clause if default value exists\n let defaultClause = \"\";\n if (defaultValue !== undefined && defaultValue !== null) {\n const defaultValueObj: PreMigrationNotNull = {\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"INLINE\",\n defaultValue: defaultValue,\n };\n defaultClause = ` DEFAULT ${buildDefault(defaultValueObj)}`;\n }\n\n // Generate MODIFY COLUMN statement\n const modifyStatement = `ALTER TABLE \\`${tableName}\\` MODIFY COLUMN IF EXISTS \\`${colName}\\` ${type} ${nullable}${defaultClause};`;\n\n changes.push({\n change: modifyStatement,\n premigrationId,\n });\n }\n }\n\n // Check for index changes\n const table = Object.values(schemaModule).find((t) => {\n const metadata = getTableMetadata(t);\n return metadata.tableName === tableName;\n });\n\n if (table) {\n const metadata = getTableMetadata(table);\n // First check indexes that exist in database but not in schema\n for (const [indexName, dbIndex] of Object.entries(dbTable.indexes)) {\n // Skip primary key and foreign key indexes\n if (indexName === \"PRIMARY\") {\n continue;\n }\n\n // Check if this is a foreign key index\n const isForeignKeyIndex = metadata.foreignKeys.some(\n (fk) => getForeignKeyName(fk) === indexName || compareForeignKey(fk, dbIndex),\n );\n if (isForeignKeyIndex) {\n continue;\n }\n\n // Check if this is a unique constraint\n const existsUniqIndex = metadata.uniqueConstraints.find(\n (uc) => getUniqueConstraintName(uc) === indexName,\n );\n let drizzleIndex = metadata.indexes.find((i) => getIndexName(i) === indexName);\n\n if (!drizzleIndex && existsUniqIndex) {\n drizzleIndex = existsUniqIndex as unknown as AnyIndexBuilder;\n }\n\n if (!drizzleIndex) {\n // Index exists in database but not in schema - create it\n const columns = 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}\\` (${columns});`,\n });\n continue;\n }\n\n // Check if index columns changed\n const dbColumns = dbIndex.columns.join(\", \");\n const drizzleColumns = getIndexColumns(drizzleIndex).join(\", \");\n if (\n dbColumns !== drizzleColumns ||\n dbIndex.unique !== drizzleIndex instanceof UniqueConstraintBuilder\n ) {\n // Drop and recreate index using database values\n changes.push({ change: `DROP INDEX \\`${indexName}\\` ON \\`${tableName}\\`;` });\n const columns = 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}\\` (${columns});`,\n });\n }\n }\n\n // First check foreign keys that exist in database but not in schema\n for (const [fkName, dbFK] of Object.entries(dbTable.foreignKeys)) {\n // Find if this column is referenced in Drizzle schema\n const drizzleFK = metadata.foreignKeys.find(\n (fk) =>\n getForeignKeyName(fk) === fkName ||\n compareForeignKey(fk, { columns: [dbFK.column], unique: false }),\n );\n\n if (!drizzleFK) {\n // Foreign key exists in database but not in schema - drop it\n changes.push({\n change: `ALTER TABLE \\`${tableName}\\` ADD CONSTRAINT \\`${fkName}\\` FOREIGN KEY (\\`${dbFK.column}\\`) REFERENCES \\`${dbFK.referencedTable}\\` (\\`${dbFK.referencedColumn}\\`);`,\n });\n continue;\n }\n }\n\n // Then check for new foreign keys that exist in schema but not in database\n for (const drizzleForeignKey of metadata.foreignKeys) {\n // Find if this foreign key exists in database\n const isDbFk = Object.keys(dbTable.foreignKeys).find((fk) => {\n let foreignKey = dbTable.foreignKeys[fk];\n return (\n fk === getForeignKeyName(drizzleForeignKey) ||\n compareForeignKey(drizzleForeignKey, { columns: [foreignKey.column], unique: false })\n );\n });\n\n if (!isDbFk) {\n // Foreign key exists in schema but not in database - create it\n if (drizzleForeignKey) {\n const fkName = getForeignKeyName(drizzleForeignKey);\n if (fkName) {\n changes.push({\n change: `ALTER TABLE \\`${tableName}\\` DROP FOREIGN KEY \\`${fkName}\\`;`,\n });\n } else {\n // @ts-ignore\n const columns = drizzleForeignKey.columns;\n const columnNames = columns?.length\n ? columns.map((c: any) => 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 }\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: any) => {\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 any).autoincrement,\n columnType: column.columnType,\n name: column.name,\n default: metadata.columns.email.hasDefault ? String(column.default) : undefined,\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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { MySqlTable, TableConfig } from \"drizzle-orm/mysql-core\";\nimport { getTableMetadata, generateDropTableStatements } from \"forge-sql-orm\";\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: any) => {\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","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport dotenv from \"dotenv\";\nimport inquirer from \"inquirer\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { generateModels } from \"./actions/generate-models\";\nimport { createMigration } from \"./actions/migrations-create\";\nimport { updateMigration } from \"./actions/migrations-update\";\nimport { dropMigration } from \"./actions/migrations-drops\";\n\nconst ENV_PATH = path.resolve(process.cwd(), \".env\");\n// 🔄 Load environment variables from `.env` file\ndotenv.config({ path: ENV_PATH });\n\nconst saveEnvFile = (config: any) => {\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((acc: any, 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()}`] = 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: any,\n defaultOutput: string,\n customAskMissingParams?: (cfg: any, questions: unknown[]) => void,\n) => {\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) => !isNaN(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);\n return { ...config, ...answers, port: parseInt(config.port ?? answers.port, 10) };\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 */\nconst getConfig = async (\n cmd: any,\n defaultOutput: string,\n customConfig?: () => any,\n customAskMissingParams?: (cfg: any, questions: unknown[]) => void,\n) => {\n let config = {\n host: cmd.host || process.env.FORGE_SQL_ORM_HOST,\n port: cmd.port\n ? parseInt(cmd.port, 10)\n : process.env.FORGE_SQL_ORM_PORT\n ? parseInt(process.env.FORGE_SQL_ORM_PORT, 10)\n : undefined,\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);\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(\"--entitiesPath <string>\", \"Path to the folder containing entities\")\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(\n cmd,\n \"./database/migration\",\n () => ({\n entitiesPath: cmd.entitiesPath || process.env.FORGE_SQL_ORM_ENTITIESPATH,\n force: cmd.force || false,\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 createMigration(config);\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);\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);\n });\n\n// 🔥 Execute CLI\n program.parse(process.argv);\n"],"names":["execSync","loadMigrationVersion","generateMigrationFile","saveMigrationFiles","columns","nullable","uuid","getTableMetadata","drizzleColumns","UniqueConstraintBuilder","generateDropTableStatements","Command"],"mappings":";;;;;;;;;;;;;;AAuFA,SAAS,kBAAkB,eAA+B;AAExD,QAAM,UAAU;AAAA;AAAA;AAGhB,MAAI,kBAAkB,cAEnB;AAAA,IACC;AAAA,IACA;AAAA,EAAA,EAGD,QAAQ,iCAAiC,2BAA2B,EAEpE,QAAQ,qDAAqD,uBAAuB,EAEpF,QAAQ,+DAA+D,uBAAuB,EAE9F,QAAQ,6BAA6B,uBAAuB,EAE5D,QAAQ,iDAAiD,mBAAmB,EAE5E,QAAQ,+DAA+D,uBAAuB,EAE9F,QAAQ,6BAA6B,uBAAuB,EAE5D,QAAQ,iDAAiD,mBAAmB,EAE5E;AAAA,IACC;AAAA,IACA;AAAA,EAAA,EAGD,QAAQ,kCAAkC,4BAA4B,EAEtE,QAAQ,sDAAsD,wBAAwB;AAGzF,MAAI,CAAC,gBAAgB,SAAS,8BAA8B,GAAG;AAC7D,sBAAkB,UAAU;AAAA,EAC9B;AAEA,SAAO;AACT;AAMO,MAAM,iBAAiB,OAAO,YAAmC;AACtE,MAAI;AAEF,UAAMA,cAAAA;AAAAA,MACJ,sDAAsD,QAAQ,IAAI,IAAI,QAAQ,QAAQ,IAAI,QAAQ,IAAI,IAAI,QAAQ,IAAI,IAAI,QAAQ,MAAM,UAAU,QAAQ,MAAM;AAAA,MAChK,EAAE,UAAU,QAAA;AAAA,IAAQ;AAItB,UAAM,UAAU,KAAK,KAAK,QAAQ,QAAQ,MAAM;AAChD,UAAM,qBAAyC,CAAA;AAE/C,QAAI,GAAG,WAAW,OAAO,GAAG;AAC1B,YAAM,eAAe,KAAK,KAAK,SAAS,oBAAoB;AAC5D,UAAI,GAAG,WAAW,YAAY,GAAG;AAC/B,cAAM,eAAe,KAAK,MAAM,GAAG,aAAa,cAAc,OAAO,CAAC;AAGtE,mBAAW,CAAC,WAAW,SAAS,KAAK,OAAO,QAAQ,aAAa,MAAM,GAAG;AACxE,gBAAM,QAAQ;AAGd,cAAI,UAAU,YAAA,EAAc,WAAW,IAAI,GAAG;AAC5C,oBAAQ;AAAA,cACN,cAAc,SAAS;AAAA,YAAA;AAAA,UAE3B;AAGA,gBAAM,eAAe,OAAO,QAAQ,MAAM,OAAO,EAAE;AAAA,YACjD,CAAC,CAAC,GAAG,GAAG,MAAM,IAAI,KAAK,YAAA,MAAkB,QAAQ;AAAA,UAAA;AAGnD,cAAI,cAAc;AAChB,kBAAM,CAAC,GAAG,GAAG,IAAI;AACjB,kBAAM,YAAY,IAAI;AACtB,kBAAM,kBACJ,cAAc,cACd,cAAc,eACd,cAAc,SACd,cAAc,YACd,cAAc;AAChB,gBAAI,CAAC,IAAI,SAAS;AAChB,sBAAQ;AAAA,gBACN,kBAAkB,IAAI,IAAI,cAAc,SAAS;AAAA,cAAA;AAAA,YAErD,WAAW,CAAC,iBAAiB;AAC3B,sBAAQ;AAAA,gBACN,kBAAkB,IAAI,IAAI,cAAc,SAAS,0BAA0B,SAAS;AAAA,cAAA;AAAA,YAGxF,OAAO;AACL,iCAAmB,SAAS,IAAI;AAAA,gBAC9B;AAAA,gBACA,cAAc;AAAA,kBACZ,WAAW,IAAI;AAAA,gBAAA;AAAA,cACjB;AAAA,YAEJ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,yBAAyB;AAAA;AAAA,oBAEhB,oBAAI,KAAA,GAAO,YAAA,CAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wDAqBa,KAAK,UAAU,oBAAoB,MAAM,CAAC,CAAC;AAAA;AAG/F,OAAG,cAAc,KAAK,KAAK,QAAQ,QAAQ,UAAU,GAAG,sBAAsB;AAG9E,UAAM,aAAa,KAAK,KAAK,QAAQ,QAAQ,WAAW;AACxD,QAAI,GAAG,WAAW,UAAU,GAAG;AAC7B,YAAM,gBAAgB,GAAG,aAAa,YAAY,OAAO;AACzD,YAAM,kBAAkB,kBAAkB,aAAa;AACvD,SAAG,cAAc,YAAY,eAAe;AAC5C,cAAQ,IAAI,8BAA8B,UAAU,EAAE;AAAA,IACxD;AAGA,UAAM,eAAe,KAAK,KAAK,QAAQ,QAAQ,YAAY;AAE3D,QAAI,GAAG,WAAW,YAAY,GAAG;AAC/B,SAAG,OAAO,cAAc,EAAE,WAAW,MAAM,OAAO,MAAM;AACxD,cAAQ,IAAI,cAAc,YAAY,EAAE;AAAA,IAC1C;AAGA,QAAI,GAAG,WAAW,OAAO,GAAG;AAC1B,YAAM,cAAc,KAAK,KAAK,SAAS,eAAe;AACtD,UAAI,GAAG,WAAW,WAAW,GAAG;AAC9B,cAAM,cAAc,KAAK,MAAM,GAAG,aAAa,aAAa,OAAO,CAAC;AAGpE,mBAAW,SAAS,YAAY,SAAS;AACvC,gBAAM,UAAU,KAAK,KAAK,QAAQ,QAAQ,GAAG,MAAM,GAAG,MAAM;AAC5D,cAAI,GAAG,WAAW,OAAO,GAAG;AAC1B,eAAG,OAAO,SAAS,EAAE,OAAO,MAAM;AAClC,oBAAQ,IAAI,uBAAuB,MAAM,GAAG,MAAM;AAAA,UACpD;AAAA,QACF;AAAA,MACF;AAGA,SAAG,OAAO,SAAS,EAAE,WAAW,MAAM,OAAO,MAAM;AACnD,cAAQ,IAAI,cAAc,OAAO,EAAE;AAAA,IACrC;AAEA,YAAQ,IAAI,sDAAsD;AAClE,YAAQ,KAAK,CAAC;AAAA,EAChB,SAAS,OAAO;AACd,YAAQ,MAAM,oCAAoC,KAAK;AACvD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;ACnPO,MAAMC,yBAAuB,OAAO,kBAA2C;AACpF,MAAI;AACF,UAAM,yBAAyB,KAAK,QAAQ,KAAK,KAAK,eAAe,mBAAmB,CAAC;AACzF,QAAI,CAAC,GAAG,WAAW,sBAAsB,GAAG;AAC1C,cAAQ,IAAI,gCAAgC;AAC5C,aAAO;AAAA,IACT;AAEA,UAAM,EAAE,kBAAA,IAAsB,MAAM,OAAO;AAC3C,YAAQ,IAAI,gCAAgC,iBAAiB,EAAE;AAC/D,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,mCAAmC,KAAK;AACtD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAMA,MAAM,iBAAiB;AASvB,SAAS,gBAAgB,SAAyB;AAChD,iBAAe,YAAY;AAI3B,YAAU,QAAQ,QAAQ,gBAAgB,0BAA0B;AAEpE,SAAO;AACT;AAOO,SAAS,kBAAkB,KAAqB;AAErD,QAAM,gBAAgB,GAAG;AAGzB,SAAO,IAAI,QAAQ,oEAAoE,EAAE,EAAE,KAAA;AAC7F;AAQO,SAASC,wBAAsB,kBAA4B,SAAyB;AACzF,QAAM,gBAAgB,IAAI,OAAO;AAGjC,QAAM,iBAAiB,iBACpB;AAAA,IACC,CAAC,MAAM,UACL,qBAAqB,aAAa,GAAG,KAAK,OAAO,kBAAkB,IAAI,EAAE,QAAQ,QAAQ,GAAG,CAAC;AAAA,EAAA,EAEhG,KAAK,IAAI;AAGZ,SAAO;AAAA;AAAA;AAAA;AAAA,EAIP,cAAc;AAAA;AAEhB;AAQO,SAASC,qBAAmB,eAAuB,SAAiB,WAAmB;AAC5F,MAAI,CAAC,GAAG,WAAW,SAAS,GAAG;AAC7B,OAAG,UAAU,WAAW,EAAE,WAAW,MAAM;AAAA,EAC7C;AAEA,QAAM,oBAAoB,KAAK,KAAK,WAAW,aAAa,OAAO,KAAK;AACxE,QAAM,qBAAqB,KAAK,KAAK,WAAW,mBAAmB;AACnE,QAAM,gBAAgB,KAAK,KAAK,WAAW,UAAU;AAGrD,KAAG,cAAc,mBAAmB,aAAa;AAGjD,KAAG,cAAc,oBAAoB,oCAAoC,OAAO,GAAG;AAInF,QAAM,cAAc,CAAA;AACpB,WAAS,IAAI,GAAG,KAAK,SAAS,KAAK;AACjC,gBAAY,KAAK,WAAW,CAAC,sBAAsB,CAAC,IAAI;AAAA,EAC1D;AAEA,QAAM,YAAY,CAAA;AAClB,WAAS,IAAI,GAAG,KAAK,SAAS,KAAK;AACjC,cAAU,KAAK,MAAM,CAAC,oBAAoB;AAAA,EAC5C;AACA,QAAM,mBAAmB;AAAA,EACzB,YAAY,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAStB,UAAU,KAAK,IAAI,CAAC;AAAA;AAAA;AAIpB,KAAG,cAAc,eAAe,gBAAgB;AAEhD,UAAQ,IAAI,6BAA6B,iBAAiB,EAAE;AAC5D,UAAQ,IAAI,mCAAmC,kBAAkB,EAAE;AACnE,UAAQ,IAAI,mCAAmC,aAAa,EAAE;AAChE;AAOA,eAAe,UAAU,YAAiD;AACxE,QAAM,CAAC,IAAI,IAAI,MAAM,WAAW,QAAe,aAAa;AAC5D,SAAO,KAAK,IAAI,CAAC,QAAQ,OAAO,OAAO,GAAG,EAAE,CAAC,CAAW;AAC1D;AAQA,eAAe,wBACb,YACA,WACwB;AACxB,QAAM,CAAC,IAAI,IAAI,MAAM,WAAW,QAA0B,uBAAuB,SAAS,IAAI;AAC9F,QAAM,SAAS;AACf,MAAI,OAAO,SAAS,KAAK,OAAO,CAAC,EAAE,cAAc,GAAG;AAClD,WAAO,OAAO,CAAC,EAAE,cAAc;AAAA,EACjC;AACA,SAAO;AACT;AAOA,eAAe,4BAA4B,YAAiD;AAC1F,QAAM,SAAS,MAAM,UAAU,UAAU;AACzC,QAAM,aAAuB,CAAA;AAE7B,aAAW,SAAS,QAAQ;AAC1B,UAAM,cAAc,MAAM,wBAAwB,YAAY,KAAK;AACnE,QAAI,aAAa;AACf,iBAAW,KAAK,WAAW;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO;AACT;AAMO,MAAM,kBAAkB,OAAO,YAAoC;AACxE,MAAI;AACF,QAAI,UAAU,MAAMF,uBAAqB,QAAQ,MAAM;AAEvD,QAAI,UAAU,GAAG;AACf,UAAI,QAAQ,OAAO;AACjB,gBAAQ;AAAA,UACN;AAAA,QAAA;AAAA,MAEJ,OAAO;AACL,gBAAQ;AAAA,UACN;AAAA,QAAA;AAEF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAGA,QAAI,CAAC,QAAQ,QAAQ,CAAC,QAAQ,QAAQ,CAAC,QAAQ,QAAQ,CAAC,QAAQ,YAAY,CAAC,QAAQ,QAAQ;AAC3F,cAAQ;AAAA,QACN;AAAA,MAAA;AAEF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,aAAa,MAAM,MAAM,iBAAiB;AAAA,MAC9C,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,IAAA,CACnB;AAED,QAAI;AACF,cAAQ,IAAI,4BAA4B,QAAQ,MAAM,EAAE;AAGxD,cAAQ,IAAI,sDAAsD;AAClE,YAAM,mBAAmB,MAAM,4BAA4B,UAAU;AAErE,UAAI,iBAAiB,WAAW,GAAG;AACjC,gBAAQ,KAAK,8CAA8C;AAAA,MAC7D,OAAO;AACL,gBAAQ,IAAI,WAAW,iBAAiB,MAAM,WAAW;AAAA,MAC3D;AAGA,YAAM,gBAAgBC,wBAAsB,kBAAkB,CAAC;AAC/DC,2BAAmB,eAAe,GAAG,QAAQ,MAAM;AAEnD,cAAQ,IAAI,mCAAmC;AAC/C,cAAQ,KAAK,CAAC;AAAA,IAChB,UAAA;AACE,YAAM,WAAW,IAAA;AAAA,IACnB;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,sCAAsC,KAAK;AACzD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AC7LA,SAAS,aAAa,cAA2C;AAC/D,QAAM,MAAM,aAAa;AACzB,QAAM,OAAO,aAAa,KAAK,YAAA;AAG/B,MAAI,QAAQ,UAAa,QAAQ,MAAM;AACrC,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,IAAI;AACd,WAAO;AAAA,EACT;AAGA,QAAM,kCAAkB,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AAGD,QAAM,mCAAmB,IAAI;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AAGD,QAAM,mBAAmB,qBAAqB,KAAK,GAAG;AAGtD,MAAI,aAAa,IAAI,IAAI,KAAK,kBAAkB;AAC9C,WAAO,GAAG,GAAG;AAAA,EACf;AAGA,MAAI,YAAY,IAAI,IAAI,GAAG;AAEzB,UAAM,UAAU,IAAI,QAAQ,MAAM,IAAI;AACtC,WAAO,IAAI,OAAO;AAAA,EACpB;AAIA,SAAO,GAAG,GAAG;AACf;AAKA,SAAS,uBAAuB,WAAmB,SAAiB,SAAyB;AAC3F,SACE,wBAAwB,SAAS,QAAQ,OAAO;AAAA,kDACG,OAAO;AAAA,kCACvB,SAAS,YAAY,OAAO;AAAA;AAAA;AAInE;AAKA,SAAS,0BACP,cACA,SACA,mBACM;AACN,QAAM,aAAa,uBAAuB,aAAa,WAAW,aAAa,SAAS,OAAO;AAC/F,UAAQ,KAAK,UAAU;AACvB,oBAAkB,KAAK,iBAAiB,KAAK,UAAU,UAAU,CAAC,IAAI;AACxE;AAKA,SAAS,sBAAsB,cAAmC,cAA8B;AAC9F,SAAO,iBAAiB,MAAM,eAAe,aAAa,YAAY;AACxE;AAKA,SAAS,wBAAwB,cAAmC,cAA8B;AAChG,QAAM,cAAc,sBAAsB,cAAc,YAAY;AACpE,SAAO,YAAY,aAAa,SAAS,YAAY,aAAa,OAAO,QAAQ,WAAW,YAAY,aAAa,OAAO;AAC9H;AAQA,SAASD,wBACP,kBAIA,SACQ;AACR,QAAM,gBAAgB,IAAI,OAAO;AACjC,QAAM,oBAA8B,CAAA;AAEpC,mBAAiB,QAAQ,QAAQ,CAAC,QAAQ,UAAU;AAClD,QAAI,CAAC,OAAO,gBAAgB;AAE1B,wBAAkB;AAAA,QAChB;AAAA,2BAA8B,aAAa,GAAG,KAAK,OAAO,OAAO,MAAM;AAAA,MAAA;AAEzE;AAAA,IACF;AAEA,UAAM,eAAe,iBAAiB,cAAc,OAAO,cAAc;AACzE,QAAI,CAAC,cAAc;AAEjB,wBAAkB;AAAA,QAChB;AAAA,2BAA8B,aAAa,GAAG,KAAK,OAAO,OAAO,MAAM;AAAA,MAAA;AAEzE;AAAA,IACF;AAEA,UAAM,eACJ,aAAa,iBAAiB,UAAa,aAAa,iBAAiB,OACrE,MACA,aAAa;AACnB,UAAM,eAAe,iBAAiB;AAEtC,QAAI,aAAa,kBAAkB,sBAAsB;AAEvD,YAAM,qBAAqB,OAAO,OAAO,QAAQ,YAAY,MAAM;AACnE,wBAAkB;AAAA,QAChB;AAAA,2BAA8B,aAAa,GAAG,KAAK,gBAAgB,kBAAkB;AAAA,MAAA;AAIvF,UAAI,cAAc;AAChB,kCAA0B,cAAc,SAAS,iBAAiB;AAAA,MACpE;AAGA,YAAM,kBAAkB,wBAAwB,cAAc,YAAY;AAC1E,wBAAkB;AAAA,QAChB;AAAA,2BAA8B,aAAa,GAAG,KAAK,6BAA6B,eAAe;AAAA,MAAA;AAIjG,YAAM,gBAAgB,iBAAiB,MAAM,KAAK,YAAY,aAAa,YAAY,CAAC;AACxF,YAAM,kBAAkB,iBAAiB,aAAa,SAAS,gCAAgC,aAAa,OAAO,MAAM,aAAa,IAAI,YAAY,aAAa;AACnK,wBAAkB;AAAA,QAChB;AAAA,2BAA8B,aAAa,GAAG,KAAK,OAAO,eAAe;AAAA,MAAA;AAAA,IAE7E,WAAW,aAAa,kBAAkB,mBAAmB;AAE3D,UAAI,cAAc;AAChB,kCAA0B,cAAc,SAAS,iBAAiB;AAAA,MACpE;AAGA,YAAM,kBAAkB,wBAAwB,cAAc,YAAY;AAC1E,wBAAkB;AAAA,QAChB;AAAA,2BAA8B,aAAa,GAAG,KAAK,6BAA6B,eAAe;AAAA,MAAA;AAIjG,wBAAkB;AAAA,QAChB;AAAA,2BAA8B,aAAa,GAAG,KAAK,OAAO,OAAO,MAAM;AAAA,MAAA;AAAA,IAE3E;AAAA,EACF,CAAC;AAED,QAAM,iBAAiB,kBAAkB,KAAK,IAAI;AAElD,SAAO;AAAA;AAAA;AAAA,EAGP,cAAc;AAAA;AAAA;AAGhB;AASA,SAAS,4BACP,eAIA,aACA,WAIA;AACA,QAAM,oBAAoB,KAAK,KAAK,WAAW,aAAa,WAAW,KAAK;AAE5E,MAAI,CAAC,GAAG,WAAW,iBAAiB,GAAG;AACrC,WAAO;AAAA,MACL,SAAS,cAAc,QAAQ,IAAI,CAAC,OAAO;AAAA,QACzC,QAAQ,EAAE,OAAO,QAAQ,QAAQ,GAAG;AAAA,QACpC,gBAAgB,EAAE;AAAA,MAAA,EAClB;AAAA,MACF,eAAe,cAAc;AAAA,IAAA;AAAA,EAEjC;AAGA,QAAM,cAAc,GAAG,aAAa,mBAAmB,OAAO;AAG9D,QAAM,iBAAiB,YACpB,MAAM,IAAI,EACV,OAAO,CAAC,SAAS,KAAK,SAAS,WAAW,CAAC,EAC3C,IAAI,CAAC,SAAS;AACb,UAAM,QAAQ,KAAK,MAAM,+BAA+B;AACxD,WAAO,QAAQ,MAAM,CAAC,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAA,IAAS;AAAA,EACxD,CAAC;AAGH,SAAO;AAAA,IACL,eAAe,cAAc;AAAA,IAC7B,SAAS,cAAc,QACpB,OAAO,CAAC,MAAM,CAAC,eAAe,SAAS,EAAE,OAAO,QAAQ,QAAQ,GAAG,CAAC,CAAC,EACrE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,QAAQ,QAAQ,GAAG,GAAG,gBAAgB,EAAE,iBAAiB;AAAA,EAAA;AAE/F;AASA,SAASC,qBAAmB,eAAuB,SAAiB,WAA4B;AAC9F,MAAI,CAAC,GAAG,WAAW,SAAS,GAAG;AAC7B,OAAG,UAAU,WAAW,EAAE,WAAW,MAAM;AAAA,EAC7C;AAEA,QAAM,oBAAoB,KAAK,KAAK,WAAW,aAAa,OAAO,KAAK;AACxE,QAAM,qBAAqB,KAAK,KAAK,WAAW,mBAAmB;AACnE,QAAM,gBAAgB,KAAK,KAAK,WAAW,UAAU;AAGrD,KAAG,cAAc,mBAAmB,aAAa;AAGjD,KAAG,cAAc,oBAAoB,oCAAoC,OAAO,GAAG;AAGnF,QAAM,cAAwB,CAAA;AAC9B,QAAM,YAAsB,CAAA;AAE5B,WAAS,IAAI,GAAG,KAAK,SAAS,KAAK;AACjC,gBAAY,KAAK,oBAAoB,CAAC,sBAAsB,CAAC,IAAI;AACjE,cAAU,KAAK,eAAe,CAAC,oBAAoB;AAAA,EACrD;AAEA,QAAM,mBAAmB;AAAA,EACzB,YAAY,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAStB,UAAU,KAAK,IAAI,CAAC;AAAA;AAAA;AAIpB,KAAG,cAAc,eAAe,gBAAgB;AAEhD,UAAQ,IAAI,6BAA6B,iBAAiB,EAAE;AAC5D,UAAQ,IAAI,mCAAmC,kBAAkB,EAAE;AACnE,UAAQ,IAAI,mCAAmC,aAAa,EAAE;AAE9D,SAAO;AACT;AAOA,MAAM,uBAAuB,OAAO,kBAA2C;AAC7E,MAAI;AACF,UAAM,yBAAyB,KAAK,QAAQ,KAAK,KAAK,eAAe,mBAAmB,CAAC;AACzF,QAAI,CAAC,GAAG,WAAW,sBAAsB,GAAG;AAC1C,cAAQ;AAAA,QACN,8CAA8C,sBAAsB;AAAA,MAAA;AAEtE,aAAO;AAAA,IACT;AAEA,UAAM,EAAE,kBAAA,IAAsB,MAAM,OAAO;AAC3C,YAAQ,IAAI,gCAAgC,iBAAiB,EAAE;AAC/D,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,mCAAmC,KAAK;AACtD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAQA,eAAe,kBACb,YACA,QACyB;AAEzB,QAAM,CAAC,OAAO,IAAI,MAAM,WAAW;AAAA,IACjC;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,CAAC,MAAM;AAAA,EAAA;AAIT,QAAM,CAAC,OAAO,IAAI,MAAM,WAAW;AAAA,IACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,CAAC,MAAM;AAAA,EAAA;AAIT,QAAM,CAAC,WAAW,IAAI,MAAM,WAAW;AAAA,IACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWA,CAAC,MAAM;AAAA,EAAA;AAGT,QAAM,SAAyB,CAAA;AAG/B,UAAQ,QAAQ,CAAC,QAAQ;AACvB,QAAI,CAAC,OAAO,IAAI,UAAU,GAAG;AAC3B,aAAO,IAAI,UAAU,IAAI;AAAA,QACvB,SAAS,CAAA;AAAA,QACT,SAAS,CAAA;AAAA,QACT,aAAa,CAAA;AAAA,MAAC;AAAA,IAElB;AACA,WAAO,IAAI,UAAU,EAAE,QAAQ,IAAI,WAAW,IAAI;AAAA,EACpD,CAAC;AAGD,UAAQ,QAAQ,CAAC,QAAQ;AACvB,QAAI,CAAC,OAAO,IAAI,UAAU,EAAE,QAAQ,IAAI,UAAU,GAAG;AACnD,aAAO,IAAI,UAAU,EAAE,QAAQ,IAAI,UAAU,IAAI;AAAA,QAC/C,SAAS,CAAA;AAAA,QACT,QAAQ,CAAC,IAAI;AAAA,MAAA;AAAA,IAEjB;AACA,WAAO,IAAI,UAAU,EAAE,QAAQ,IAAI,UAAU,EAAE,QAAQ,KAAK,IAAI,WAAW;AAAA,EAC7E,CAAC;AAGD,cAAY,QAAQ,CAAC,QAAQ;AAC3B,QAAI,CAAC,OAAO,IAAI,UAAU,EAAE,YAAY,IAAI,eAAe,GAAG;AAC5D,aAAO,IAAI,UAAU,EAAE,YAAY,IAAI,eAAe,IAAI;AAAA,QACxD,QAAQ,IAAI;AAAA,QACZ,iBAAiB,IAAI;AAAA,QACrB,kBAAkB,IAAI;AAAA,MAAA;AAAA,IAE1B;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAOA,SAAS,mBAAmB,WAA2B;AAErD,MAAI,aAAa,UAAU,QAAQ,aAAa,EAAE,EAAE,YAAA;AAGpD,eAAa,WAAW,QAAQ,UAAU,EAAE;AAE5C,SAAO;AACT;AAOA,SAAS,kBAAkB,IAA+B;AAExD,SAAO,GAAG;AACZ;AAOA,SAAS,aAAa,OAAgC;AAEpD,SAAO,MAAM;AACf;AAOA,SAAS,wBAAwB,IAAqC;AAEpE,SAAO,GAAG;AACZ;AAOA,SAAS,gBAAgB,OAAkC;AAEzD,SAAO,MAAM,QAAQ,IAAI,CAAC,QAAQ,IAAI,IAAI;AAC5C;AAEA,SAAS,kBACP,IACA,EAAE,WACF;AAEA,QAAM,WAAqB,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI;AACvD,SAAO,SAAS,KAAA,EAAO,KAAK,GAAG,MAAM,QAAQ,KAAA,EAAO,KAAK,GAAG;AAC9D;AASA,SAAS,sBACP,eACA,UACA,cAIA;AACA,QAAM,UAAyD,CAAA;AAC/D,QAAM,gBAAqD,CAAA;AAE3D,aAAW,CAAC,WAAW,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAC3D,UAAM,iBAAiB,cAAc,SAAS;AAE9C,QAAI,CAAC,gBAAgB;AAEnB,YAAM,UAAU,OAAO,QAAQ,QAAQ,OAAO,EAC3C,IAAI,CAAC,CAAC,SAAS,GAAG,MAAM;AACvB,cAAM,OAAO,IAAI;AACjB,cAAM,WAAW,IAAI,gBAAgB,QAAQ,SAAS;AACtD,cAAM,gBAAgB,IAAI,MAAM,SAAS,gBAAgB,IAAI,mBAAmB;AAChF,eAAO,KAAK,OAAO,MAAM,IAAI,IAAI,QAAQ,IAAI,aAAa,GAAG,KAAA;AAAA,MAC/D,CAAC,EACA,KAAK,OAAO;AAEf,cAAQ,KAAK,EAAE,QAAQ,gCAAgC,SAAS;AAAA,IAAW,OAAO;AAAA,KAAQ;AAG1F,iBAAW,CAAC,WAAW,OAAO,KAAK,OAAO,QAAQ,QAAQ,OAAO,GAAG;AAElE,YAAI,cAAc,WAAW;AAC3B;AAAA,QACF;AAGA,cAAM,oBAAoB,QAAQ,QAAQ,KAAK,CAAC,YAAY;AAC1D,gBAAM,SAAS,QAAQ,QAAQ,OAAO;AACtC,iBAAO,UAAU,OAAO,eAAe,SAAS,OAAO,MAAM,SAAS,aAAa;AAAA,QACrF,CAAC;AAED,YAAI,mBAAmB;AACrB;AAAA,QACF;AAGA,cAAMC,WAAU,QAAQ,QAAQ,IAAI,CAAC,QAAQ,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI;AACpE,cAAM,SAAS,QAAQ,SAAS,YAAY;AAC5C,gBAAQ,KAAK;AAAA,UACX,QAAQ,WAAW,MAAM,0BAA0B,SAAS,WAAW,SAAS,OAAOA,QAAO;AAAA,QAAA,CAC/F;AAAA,MACH;AAGA,iBAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,QAAQ,WAAW,GAAG;AAChE,gBAAQ,KAAK;AAAA,UACX,QAAQ,iBAAiB,SAAS,uBAAuB,MAAM,qBAAqB,KAAK,MAAM,oBAAoB,KAAK,eAAe,SAAS,KAAK,gBAAgB;AAAA,QAAA,CACtK;AAAA,MACH;AACA;AAAA,IACF;AAGA,eAAW,CAAC,SAAS,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,GAAG;AAC9D,YAAM,aAAa,OAAO,OAAO,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO;AAE/E,UAAI,CAAC,YAAY;AAEf,cAAM,OAAO,MAAM;AACnB,cAAMC,YAAW,MAAM,gBAAgB,QAAQ,SAAS;AACxD,YAAI,iBAAiBA,cAAa,aAAaC,KAAAA,GAAA,IAAS;AACxD,cAAM,eAAe,MAAM;AAC3B,YAAID,cAAa,YAAY;AAC3B,2BAAiBC,KAAAA,GAAA;AACjB,wBAAc,cAAc,IAAI;AAAA,YAC9B;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,eAAe;AAAA,YACf;AAAA,UAAA;AAAA,QAEJ;AACA,gBAAQ,KAAK;AAAA,UACX,QAAQ,iBAAiB,SAAS,iCAAiC,OAAO,MAAM,IAAI,IAAID,SAAQ,IAC9F,iBAAiB,UAAa,iBAAiB,OAC3C,KACA,WAAW,aAAa;AAAA,YAItB;AAAA,YAEA;AAAA,UAAA,CACD,CAAC,EACR;AAAA,UACA;AAAA,QAAA,CACD;AACD;AAAA,MACF;AAGA,YAAM,mBAAmB,mBAAmB,MAAM,WAAW;AAC7D,YAAM,wBAAwB,mBAAmB,WAAW,WAAA,CAAY;AACxE,YAAM,WAAW,MAAM,gBAAgB,QAAQ,SAAS;AACxD,YAAM,cAAc,aAAa;AACjC,YAAM,mBAAmB,WAAW;AAGpC,YAAM,cAAc,qBAAqB;AAGzC,YAAM,qBAAqB,gBAAgB;AAG3C,YAAM,oBAAoB,WAAW,YAAY,QAAQ,WAAW,YAAY;AAChF,YAAM,eAAe,MAAM,mBAAmB,QAAQ,MAAM,mBAAmB;AAC/E,YAAM,iBACJ,qBAAqB,gBAAgB,WAAW,YAAY,MAAM;AAGpE,UAAI,eAAe,sBAAsB,gBAAgB;AACvD,cAAM,OAAO,MAAM;AACnB,cAAM,eAAe,MAAM;AAG3B,YAAI,iBAAqC;AACzC,YAAI,eAAe,CAAC,kBAAkB;AAEpC,2BAAiBC,KAAAA,GAAA;AACjB,wBAAc,cAAc,IAAI;AAAA,YAC9B;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,eAAe;AAAA,YACf;AAAA,UAAA;AAAA,QAEJ;AAGA,YAAI,gBAAgB;AACpB,YAAI,iBAAiB,UAAa,iBAAiB,MAAM;AACvD,gBAAM,kBAAuC;AAAA,YAI3C;AAAA,YAEA;AAAA,UAAA;AAEF,0BAAgB,YAAY,aAAa,eAAe,CAAC;AAAA,QAC3D;AAGA,cAAM,kBAAkB,iBAAiB,SAAS,gCAAgC,OAAO,MAAM,IAAI,IAAI,QAAQ,GAAG,aAAa;AAE/H,gBAAQ,KAAK;AAAA,UACX,QAAQ;AAAA,UACR;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IACF;AAGA,UAAM,QAAQ,OAAO,OAAO,YAAY,EAAE,KAAK,CAAC,MAAM;AACpD,YAAM,WAAWC,YAAAA,iBAAiB,CAAC;AACnC,aAAO,SAAS,cAAc;AAAA,IAChC,CAAC;AAED,QAAI,OAAO;AACT,YAAM,WAAWA,YAAAA,iBAAiB,KAAK;AAEvC,iBAAW,CAAC,WAAW,OAAO,KAAK,OAAO,QAAQ,QAAQ,OAAO,GAAG;AAElE,YAAI,cAAc,WAAW;AAC3B;AAAA,QACF;AAGA,cAAM,oBAAoB,SAAS,YAAY;AAAA,UAC7C,CAAC,OAAO,kBAAkB,EAAE,MAAM,aAAa,kBAAkB,IAAI,OAAO;AAAA,QAAA;AAE9E,YAAI,mBAAmB;AACrB;AAAA,QACF;AAGA,cAAM,kBAAkB,SAAS,kBAAkB;AAAA,UACjD,CAAC,OAAO,wBAAwB,EAAE,MAAM;AAAA,QAAA;AAE1C,YAAI,eAAe,SAAS,QAAQ,KAAK,CAAC,MAAM,aAAa,CAAC,MAAM,SAAS;AAE7E,YAAI,CAAC,gBAAgB,iBAAiB;AACpC,yBAAe;AAAA,QACjB;AAEA,YAAI,CAAC,cAAc;AAEjB,gBAAM,UAAU,QAAQ,QAAQ,IAAI,CAAC,QAAQ,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI;AACpE,gBAAM,SAAS,QAAQ,SAAS,YAAY;AAC5C,kBAAQ,KAAK;AAAA,YACX,QAAQ,UAAU,MAAM,yBAAyB,SAAS,WAAW,SAAS,OAAO,OAAO;AAAA,UAAA,CAC7F;AACD;AAAA,QACF;AAGA,cAAM,YAAY,QAAQ,QAAQ,KAAK,IAAI;AAC3C,cAAMC,kBAAiB,gBAAgB,YAAY,EAAE,KAAK,IAAI;AAC9D,YACE,cAAcA,mBACd,QAAQ,WAAW,wBAAwBC,iBAAAA,yBAC3C;AAEA,kBAAQ,KAAK,EAAE,QAAQ,gBAAgB,SAAS,WAAW,SAAS,OAAO;AAC3E,gBAAM,UAAU,QAAQ,QAAQ,IAAI,CAAC,QAAQ,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI;AACpE,gBAAM,SAAS,QAAQ,SAAS,YAAY;AAC5C,kBAAQ,KAAK;AAAA,YACX,QAAQ,WAAW,MAAM,yBAAyB,SAAS,WAAW,SAAS,OAAO,OAAO;AAAA,UAAA,CAC9F;AAAA,QACH;AAAA,MACF;AAGA,iBAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,QAAQ,WAAW,GAAG;AAEhE,cAAM,YAAY,SAAS,YAAY;AAAA,UACrC,CAAC,OACC,kBAAkB,EAAE,MAAM,UAC1B,kBAAkB,IAAI,EAAE,SAAS,CAAC,KAAK,MAAM,EAAiB,CAAC;AAAA,QAAA;AAGnE,YAAI,CAAC,WAAW;AAEd,kBAAQ,KAAK;AAAA,YACX,QAAQ,iBAAiB,SAAS,uBAAuB,MAAM,qBAAqB,KAAK,MAAM,oBAAoB,KAAK,eAAe,SAAS,KAAK,gBAAgB;AAAA,UAAA,CACtK;AACD;AAAA,QACF;AAAA,MACF;AAGA,iBAAW,qBAAqB,SAAS,aAAa;AAEpD,cAAM,SAAS,OAAO,KAAK,QAAQ,WAAW,EAAE,KAAK,CAAC,OAAO;AAC3D,cAAI,aAAa,QAAQ,YAAY,EAAE;AACvC,iBACE,OAAO,kBAAkB,iBAAiB,KAC1C,kBAAkB,mBAAmB,EAAE,SAAS,CAAC,WAAW,MAAM,EAAiB,CAAC;AAAA,QAExF,CAAC;AAED,YAAI,CAAC,QAAQ;AAEX,cAAI,mBAAmB;AACrB,kBAAM,SAAS,kBAAkB,iBAAiB;AAClD,gBAAI,QAAQ;AACV,sBAAQ,KAAK;AAAA,gBACX,QAAQ,iBAAiB,SAAS,0BAA0B,MAAM;AAAA,cAAA,CACnE;AAAA,YACH,OAAO;AAEL,oBAAM,UAAU,kBAAkB;AAClC,oBAAM,cAAc,SAAS,SACzB,QAAQ,IAAI,CAAC,MAAW,EAAE,IAAI,EAAE,KAAK,IAAI,IACzC;AACJ,sBAAQ;AAAA,gBACN,+BAA+B,SAAS,oEAAoE,WAAW;AAAA,cAAA;AAAA,YAE3H;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,cAAA;AACpB;AAMO,MAAM,kBAAkB,OAAO,YAAiB;AACrD,MAAI;AACF,QAAI,UAAU,MAAM,qBAAqB,QAAQ,MAAM;AACvD,UAAM,cAAc;AAEpB,QAAI,UAAU,GAAG;AACf,cAAQ;AAAA,QACN;AAAA,MAAA;AAEF,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,eAAW;AAGX,UAAM,aAAa,MAAM,MAAM,iBAAiB;AAAA,MAC9C,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,IAAA,CACnB;AAED,QAAI;AAEF,YAAM,WAAW,MAAM,kBAAkB,YAAY,QAAQ,MAAM;AAGnE,YAAM,aAAa,KAAK,QAAQ,QAAQ,cAAc,WAAW;AACjE,UAAI,CAAC,GAAG,WAAW,UAAU,GAAG;AAC9B,cAAM,IAAI,MAAM,6BAA6B,UAAU,EAAE;AAAA,MAC3D;AAEA,YAAM,eAAe,MAAM,OAAO;AAClC,UAAI,CAAC,cAAc;AACjB,cAAM,IAAI,MAAM,2BAA2B,UAAU,8BAA8B;AAAA,MACrF;AAGA,YAAM,gBAA+B,CAAA;AAGrC,YAAM,SAAS,OAAO,OAAO,YAAY;AAEzC,aAAO,QAAQ,CAAC,UAAU;AACxB,cAAM,WAAWF,YAAAA,iBAAiB,KAAK;AACvC,YAAI,SAAS,WAAW;AAEtB,gBAAM,UAAyC,CAAA;AAC/C,iBAAO,QAAQ,SAAS,OAAO,EAAE,QAAQ,CAAC,CAAC,MAAM,MAAM,MAAM;AAC3D,oBAAQ,IAAI,IAAI;AAAA,cACd,MAAM,OAAO;AAAA,cACb,SAAS,OAAO;AAAA,cAChB,eAAgB,OAAe;AAAA,cAC/B,YAAY,OAAO;AAAA,cACnB,MAAM,OAAO;AAAA,cACb,SAAS,SAAS,QAAQ,MAAM,aAAa,OAAO,OAAO,OAAO,IAAI;AAAA,cACtE,YAAY,MAAM,OAAO,WAAA;AAAA,YAAW;AAAA,UAExC,CAAC;AACD,wBAAc,SAAS,SAAS,IAAI;AAAA,QACtC;AAAA,MACF,CAAC;AAED,UAAI,OAAO,KAAK,aAAa,EAAE,WAAW,GAAG;AAC3C,cAAM,IAAI,MAAM,uCAAuC,UAAU,EAAE;AAAA,MACrE;AAEA,cAAQ,IAAI,iBAAiB,OAAO,KAAK,aAAa,CAAC;AAGvD,YAAM,mBAAmB;AAAA,QACvB,sBAAsB,eAAe,UAAU,YAAY;AAAA,QAC3D;AAAA,QACA,QAAQ;AAAA,MAAA;AAGV,UAAI,iBAAiB,QAAQ,QAAQ;AAEnC,cAAM,gBAAgBL,wBAAsB,kBAAkB,OAAO;AAGrE,YAAIC,qBAAmB,eAAe,SAAS,QAAQ,MAAM,GAAG;AAC9D,kBAAQ,IAAI,mCAAmC;AAAA,QACjD;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB,OAAO;AACL,gBAAQ,IAAI,uCAAuC;AACnD,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF,UAAA;AACE,YAAM,WAAW,IAAA;AAAA,IACnB;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,oCAAoC,KAAK;AACvD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;ACv6BA,SAAS,sBAAsB,SAAyB;AACtD,QAAM,0BAAU,KAAA;AAChB,QAAM,YAAY,IAAI,QAAA;AACtB,SAAO,cAAc,OAAO,IAAI,SAAS;AAC3C;AAQA,SAAS,sBAAsB,kBAA4B,SAAyB;AAClF,QAAM,SAAS,sBAAsB,OAAO;AAE5C,QAAM,iBAAiB,iBACpB;AAAA,IACC,CAAC,MAAM,UAAU,qBAAqB,MAAM,IAAI,KAAK,OAAQ,IAAI;AAAA;AAAA,EAAA,EAElE,KAAK,IAAI;AAGZ,SAAO;AAAA;AAAA;AAAA;AAAA,EAIP,cAAc;AAAA;AAEhB;AAQA,SAAS,mBAAmB,eAAuB,SAAiB,WAAmB;AACrF,MAAI,CAAC,GAAG,WAAW,SAAS,GAAG;AAC7B,OAAG,UAAU,WAAW,EAAE,WAAW,MAAM;AAAA,EAC7C;AAEA,QAAM,oBAAoB,KAAK,KAAK,WAAW,aAAa,OAAO,KAAK;AACxE,QAAM,qBAAqB,KAAK,KAAK,WAAW,mBAAmB;AACnE,QAAM,gBAAgB,KAAK,KAAK,WAAW,UAAU;AAGrD,KAAG,cAAc,mBAAmB,aAAa;AAGjD,KAAG,cAAc,oBAAoB,oCAAoC,OAAO,GAAG;AAGnF,QAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBzB,KAAG,cAAc,eAAe,gBAAgB;AAEhD,UAAQ,IAAI,6BAA6B,iBAAiB,EAAE;AAC5D,UAAQ,IAAI,mCAAmC,kBAAkB,EAAE;AACnE,UAAQ,IAAI,mCAAmC,aAAa,EAAE;AAChE;AAMO,MAAM,gBAAgB,OAAO,YAAiB;AACnD,MAAI;AAEF,UAAM,UAAU;AAGhB,UAAM,aAAa,KAAK,QAAQ,QAAQ,cAAc,WAAW;AACjE,QAAI,CAAC,GAAG,WAAW,UAAU,GAAG;AAC9B,YAAM,IAAI,MAAM,6BAA6B,UAAU,EAAE;AAAA,IAC3D;AAEA,UAAM,eAAe,MAAM,OAAO;AAClC,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,2BAA2B,UAAU,8BAA8B;AAAA,IACrF;AAGA,UAAM,SAAS,OAAO,OAAO,YAAY;AAEzC,QAAI,OAAO,WAAW,GAAG;AACvB,YAAM,IAAI,MAAM,uCAAuC,UAAU,EAAE;AAAA,IACrE;AAGA,UAAM,aAAa,OAChB,IAAI,CAAC,UAAU;AACd,YAAM,WAAWI,YAAAA,iBAAiB,KAAK;AACvC,aAAO,SAAS;AAAA,IAClB,CAAC,EACA,OAAO,OAAO;AAEjB,YAAQ,IAAI,iBAAiB,UAAU;AAGvC,UAAM,iBAAiBG,YAAAA,4BAA4B,UAAU;AAG7D,UAAM,gBAAgB,sBAAsB,gBAAgB,OAAO;AACnE,uBAAmB,eAAe,SAAS,QAAQ,MAAM;AAEzD,YAAQ,IAAI,mCAAmC;AAC/C,YAAQ,KAAK,CAAC;AAAA,EAChB,SAAS,OAAO;AACd,YAAQ,MAAM,sCAAsC,KAAK;AACzD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AC9HA,MAAM,WAAW,KAAK,QAAQ,QAAQ,IAAA,GAAO,MAAM;AAEnD,OAAO,OAAO,EAAE,MAAM,UAAU;AAEhC,MAAM,cAAc,CAAC,WAAgB;AACnC,MAAI,aAAa;AACjB,QAAM,cAAc;AAEpB,MAAI,GAAG,WAAW,WAAW,GAAG;AAC9B,iBAAa,GAAG,aAAa,aAAa,MAAM;AAAA,EAClD;AAEA,QAAM,UAAU,WACb,MAAM,IAAI,EACV,OAAO,CAAC,SAAS,KAAK,KAAA,MAAW,MAAM,CAAC,KAAK,WAAW,GAAG,CAAC,EAC5D,OAAO,CAAC,KAAU,SAAS;AAC1B,UAAM,CAAC,KAAK,GAAG,KAAK,IAAI,KAAK,MAAM,GAAG;AACtC,QAAI,GAAG,IAAI,MAAM,KAAK,GAAG;AACzB,WAAO;AAAA,EACT,GAAG,CAAA,CAAE;AAEP,SAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC/C,YAAQ,iBAAiB,IAAI,YAAA,CAAa,EAAE,IAAI;AAAA,EAClD,CAAC;AAED,QAAM,oBAAoB,OAAO,QAAQ,OAAO,EAC7C,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,EACvC,KAAK,IAAI;AAEZ,KAAG,cAAc,aAAa,mBAAmB,EAAE,UAAU,QAAQ;AAErE,UAAQ,IAAI,oEAAoE;AAClF;AASA,MAAM,mBAAmB,OACvB,QACA,eACA,2BACG;AACH,QAAM,YAAuB,CAAA;AAE7B,MAAI,CAAC,OAAO;AACV,cAAU,KAAK;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAEH,MAAI,CAAC,OAAO;AACV,cAAU,KAAK;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,MACT,UAAU,CAAC,UAAkB,CAAC,MAAM,SAAS,OAAO,EAAE,CAAC;AAAA,IAAA,CACxD;AAEH,MAAI,CAAC,OAAO;AACV,cAAU,KAAK;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAEH,MAAI,CAAC,OAAO;AACV,cAAU,KAAK;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,IAAA,CACP;AAEH,MAAI,CAAC,OAAO;AACV,cAAU,KAAK;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,IAAA,CACV;AAEH,MAAI,CAAC,OAAO;AACV,cAAU,KAAK;AAAA,MACb,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAGH,MAAI,wBAAwB;AAC1B,2BAAuB,QAAQ,SAAS;AAAA,EAC1C;AAGA,MAAI,UAAU,SAAS,GAAG;AAExB,UAAM,UAAU,MAAM,SAAS,OAAO,SAAS;AAC/C,WAAO,EAAE,GAAG,QAAQ,GAAG,SAAS,MAAM,SAAS,OAAO,QAAQ,QAAQ,MAAM,EAAE,EAAA;AAAA,EAChF;AAEA,SAAO;AACT;AAWA,MAAM,YAAY,OAChB,KACA,eACA,cACA,2BACG;AACH,MAAI,SAAS;AAAA,IACX,MAAM,IAAI,QAAQ,QAAQ,IAAI;AAAA,IAC9B,MAAM,IAAI,OACN,SAAS,IAAI,MAAM,EAAE,IACrB,QAAQ,IAAI,qBACV,SAAS,QAAQ,IAAI,oBAAoB,EAAE,IAC3C;AAAA,IACN,MAAM,IAAI,QAAQ,QAAQ,IAAI;AAAA,IAC9B,UAAU,IAAI,YAAY,QAAQ,IAAI;AAAA,IACtC,QAAQ,IAAI,UAAU,QAAQ,IAAI;AAAA,IAClC,QAAQ,IAAI,UAAU,QAAQ,IAAI;AAAA,EAAA;AAIpC,MAAI,cAAc;AAChB,aAAS,EAAE,GAAG,QAAQ,GAAG,eAAa;AAAA,EACxC;AAEA,QAAM,OAAO,MAAM,iBAAiB,QAAQ,eAAe,sBAAsB;AACjF,MAAI,IAAI,SAAS;AACf,gBAAY,IAAI;AAAA,EAClB;AACA,SAAO;AACT;AAGO,MAAM,UAAU,IAAIC,UAAAA,QAAA;AAC3B,QAAQ,QAAQ,OAAO;AAGvB,QACG,QAAQ,gBAAgB,EACxB,YAAY,4CAA4C,EACxD,OAAO,mBAAmB,eAAe,EACzC,OAAO,mBAAmB,eAAe,EACzC,OAAO,mBAAmB,eAAe,EACzC,OAAO,uBAAuB,mBAAmB,EACjD,OAAO,qBAAqB,eAAe,EAC3C,OAAO,qBAAqB,0BAA0B,EACtD,OAAO,2BAA2B,2BAA2B,EAC7D,OAAO,aAAa,iCAAiC,EACrD,OAAO,OAAO,QAAQ;AACrB,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA,OAAO;AAAA,MACL,cAAc,IAAI,gBAAgB,QAAQ,IAAI;AAAA,IAAA;AAAA,IAEhD,CAAC,KAAK,cAAyB;AAC7B,UAAI,CAAC,IAAI,cAAc;AACrB,kBAAU,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QAAA,CACV;AAAA,MACH;AAAA,IACF;AAAA,EAAA;AAEF,QAAM,eAAe,MAAM;AAC7B,CAAC;AAGH,QACG,QAAQ,mBAAmB,EAC3B,YAAY,wDAAwD,EACpE,OAAO,mBAAmB,eAAe,EACzC,OAAO,mBAAmB,eAAe,EACzC,OAAO,mBAAmB,eAAe,EACzC,OAAO,uBAAuB,mBAAmB,EACjD,OAAO,qBAAqB,eAAe,EAC3C,OAAO,qBAAqB,4BAA4B,EACxD,OAAO,2BAA2B,wCAAwC,EAC1E,OAAO,WAAW,yCAAyC,EAC3D,OAAO,aAAa,iCAAiC,EACrD,OAAO,OAAO,QAAQ;AACrB,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA,OAAO;AAAA,MACL,cAAc,IAAI,gBAAgB,QAAQ,IAAI;AAAA,MAC9C,OAAO,IAAI,SAAS;AAAA,IAAA;AAAA,IAEtB,CAAC,KAAK,cAAyB;AAC7B,UAAI,CAAC,IAAI;AACP,kBAAU,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QAAA,CACV;AAAA,IACL;AAAA,EAAA;AAEF,QAAM,gBAAgB,MAAM;AAC9B,CAAC;AAGH,QACG,QAAQ,mBAAmB,EAC3B,YAAY,qDAAqD,EACjE,OAAO,mBAAmB,eAAe,EACzC,OAAO,mBAAmB,eAAe,EACzC,OAAO,mBAAmB,eAAe,EACzC,OAAO,uBAAuB,mBAAmB,EACjD,OAAO,qBAAqB,eAAe,EAC3C,OAAO,qBAAqB,4BAA4B,EACxD,OAAO,2BAA2B,wCAAwC,EAC1E,OAAO,aAAa,iCAAiC,EACrD,OAAO,OAAO,QAAQ;AACrB,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA,OAAO;AAAA,MACL,cAAc,IAAI,gBAAgB,QAAQ,IAAI;AAAA,IAAA;AAAA,IAEhD,CAAC,KAAK,cAAyB;AAC7B,UAAI,CAAC,IAAI;AACP,kBAAU,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QAAA,CACV;AAAA,IACL;AAAA,EAAA;AAEF,QAAM,gBAAgB,MAAM;AAC9B,CAAC;AAGH,QACG,QAAQ,iBAAiB,EACzB,YAAY,uEAAuE,EACnF,OAAO,mBAAmB,eAAe,EACzC,OAAO,mBAAmB,eAAe,EACzC,OAAO,mBAAmB,eAAe,EACzC,OAAO,uBAAuB,mBAAmB,EACjD,OAAO,qBAAqB,eAAe,EAC3C,OAAO,qBAAqB,4BAA4B,EACxD,OAAO,2BAA2B,wCAAwC,EAC1E,OAAO,aAAa,iCAAiC,EACrD,OAAO,OAAO,QAAQ;AACrB,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA,OAAO;AAAA,MACL,cAAc,IAAI,gBAAgB,QAAQ,IAAI;AAAA,IAAA;AAAA,IAEhD,CAAC,KAAK,cAAyB;AAC7B,UAAI,CAAC,IAAI;AACP,kBAAU,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QAAA,CACV;AAAA,IACL;AAAA,EAAA;AAEF,QAAM,cAAc,MAAM;AAC5B,CAAC;AAGD,QAAQ,MAAM,QAAQ,IAAI;;"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/actions/generate-models.ts","../src/actions/migrations-create.ts","../src/actions/migrations-update.ts","../src/actions/migrations-drops.ts","../src/cli.ts"],"sourcesContent":["import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { execSync } from \"child_process\";\n\n/**\n * Options for model generation\n */\ninterface 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, any>;\n foreignKeys: Record<string, any>;\n uniqueConstraints: Record<string, any>;\n checkConstraint: Record<string, any>;\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/**\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 await 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 // Process metadata to create version map\n const metaDir = path.join(options.output, \"meta\");\n const additionalMetadata: AdditionalMetadata = {};\n\n if (fs.existsSync(metaDir)) {\n const snapshotFile = path.join(metaDir, \"0000_snapshot.json\");\n if (fs.existsSync(snapshotFile)) {\n const snapshotData = JSON.parse(fs.readFileSync(snapshotFile, \"utf-8\"));\n\n // Process each table from the snapshot\n for (const [tableName, tableData] of Object.entries(snapshotData.tables)) {\n const table = tableData as TableMetadata;\n\n // Check if table name starts with 'a_' and warn about cache\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 // Find version field in columns\n const versionField = Object.entries(table.columns).find(\n ([_, col]) => col.name.toLowerCase() === options.versionField,\n );\n\n if (versionField) {\n const [_, col] = versionField;\n const fieldType = col.type;\n const isSupportedType =\n fieldType === \"datetime\" ||\n fieldType === \"timestamp\" ||\n fieldType === \"int\" ||\n fieldType === \"number\" ||\n fieldType === \"decimal\";\n if (!col.notNull) {\n console.warn(\n `Version field \"${col.name}\" in table ${tableName} is nullable. Versioning may not work correctly.`,\n );\n } else if (!isSupportedType) {\n console.warn(\n `Version field \"${col.name}\" in table ${tableName} has unsupported type \"${fieldType}\". ` +\n `Only datetime, timestamp, int, and decimal types are supported for versioning. Versioning will be skipped.`,\n );\n } else {\n additionalMetadata[tableName] = {\n tableName,\n versionField: {\n fieldName: col.name,\n },\n };\n }\n }\n }\n }\n }\n\n // Create version metadata file\n const versionMetadataContent = `/**\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 fs.writeFileSync(path.join(options.output, \"index.ts\"), versionMetadataContent);\n\n // Replace MySQL types in the generated schema file\n const schemaPath = path.join(options.output, \"schema.ts\");\n if (fs.existsSync(schemaPath)) {\n const schemaContent = fs.readFileSync(schemaPath, \"utf-8\");\n const modifiedContent = replaceMySQLTypes(schemaContent);\n fs.writeFileSync(schemaPath, modifiedContent);\n console.log(`✅ Updated schema types in: ${schemaPath}`);\n }\n\n // Remove migration files and meta directory if they exist\n const migrationDir = path.join(options.output, \"migrations\");\n\n if (fs.existsSync(migrationDir)) {\n fs.rmSync(migrationDir, { recursive: true, force: true });\n console.log(`✅ Removed: ${migrationDir}`);\n }\n\n // Read journal and remove corresponding SQL file\n if (fs.existsSync(metaDir)) {\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\n // Remove SQL files for each entry\n for (const entry of journalData.entries) {\n const sqlFile = path.join(options.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 // Remove meta directory after processing\n fs.rmSync(metaDir, { recursive: true, force: true });\n console.log(`✅ Removed: ${metaDir}`);\n }\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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"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<any[]>(\"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 const result = rows as CreateTableRow[];\n if (result.length > 0 && result[0][\"Create Table\"]) {\n return result[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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport mysql from \"mysql2/promise\";\nimport { 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\ninterface DrizzleColumn {\n type: string;\n notNull: boolean;\n autoincrement?: boolean;\n columnType?: any;\n name: string;\n default?: string;\n getSQLType: () => string;\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 =\n preMigration.defaultValue === undefined || preMigration.defaultValue === null\n ? \"?\"\n : 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\n const updateStatement = generateUpdateStatement(preMigration, defaultValue);\n migrationLineList.push(\n `\\nmigrationRunner.enqueue(\"${versionPrefix}${index}_UPDATE_EXISTS_RECORDS\", \"${updateStatement}\")`,\n );\n\n // Step 3: Apply the MODIFY statement\n migrationLineList.push(\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/**\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\n const prevStatements = prevContent\n .split(\"\\n\")\n .filter((line) => line.includes(\".enqueue(\"))\n .map((line) => {\n const match = line.match(/\\.enqueue\\([^,]+,\\s*\"([^\"]+)\"/);\n return match ? match[1].replace(/\\s+/g, \" \").trim() : \"\";\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.includes(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\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 fcolumns.sort().join(\",\") === columns.sort().join(\",\");\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, any>,\n): {\n changes: { change: string; premigrationId?: string }[];\n preMigrations: Record<string, PreMigrationNotNull>;\n} {\n const changes: { change: string; premigrationId?: string }[] = [];\n const preMigrations: Record<string, PreMigrationNotNull> = {};\n // First check existing tables in database\n for (const [tableName, dbTable] of Object.entries(dbSchema)) {\n const drizzleColumns = drizzleSchema[tableName];\n\n if (!drizzleColumns) {\n // Table exists in database but not in schema - create it\n const columns = Object.entries(dbTable.columns)\n .map(([colName, col]) => {\n const type = col.COLUMN_TYPE;\n const nullable = col.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n const autoIncrement = col.EXTRA.includes(\"auto_increment\") ? \"AUTO_INCREMENT\" : \"\";\n return `\\`${colName}\\` ${type} ${nullable} ${autoIncrement}`.trim();\n })\n .join(\",\\n \");\n\n changes.push({ change: `CREATE TABLE if not exists \\`${tableName}\\` (\\n ${columns}\\n);` });\n\n // Create indexes for new table\n for (const [indexName, dbIndex] of Object.entries(dbTable.indexes)) {\n // Skip primary key and foreign key indexes\n if (indexName === \"PRIMARY\") {\n continue;\n }\n\n // Check if any column in this index is a foreign key\n const isForeignKeyIndex = dbIndex.columns.some((colName) => {\n const column = dbTable.columns[colName];\n return column && column.COLUMN_KEY === \"MUL\" && column.EXTRA.includes(\"foreign key\");\n });\n\n if (isForeignKeyIndex) {\n continue;\n }\n\n // Create index\n const columns = 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}\\` (${columns});`,\n });\n }\n\n // Create foreign keys for new table\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 continue;\n }\n\n // Check for column changes in existing tables\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 // Column exists in database but not in schema - create it\n const type = dbCol.COLUMN_TYPE;\n const nullable = dbCol.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n let premigrationId = nullable === \"NOT NULL\" ? uuid() : undefined;\n const defaultValue = dbCol.COLUMN_DEFAULT;\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 changes.push({\n change: `ALTER TABLE \\`${tableName}\\` ADD COLUMN IF NOT EXISTS \\`${colName}\\` ${type} ${nullable} ${\n defaultValue === undefined || defaultValue === null\n ? \"\"\n : `DEFAULT ${buildDefault({\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"INLINE\",\n defaultValue: defaultValue,\n })}`\n };`,\n premigrationId,\n });\n continue;\n }\n\n // Check for column changes (type, nullability, or default value)\n const normalizedDbType = normalizeMySQLType(dbCol.COLUMN_TYPE);\n const normalizedDrizzleType = normalizeMySQLType(drizzleCol.getSQLType());\n const nullable = dbCol.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n const dbIsNotNull = nullable === \"NOT NULL\";\n const drizzleIsNotNull = drizzleCol.notNull;\n\n // Check if type has changed\n const typeChanged = normalizedDbType !== normalizedDrizzleType;\n\n // Check if nullability has changed\n const nullabilityChanged = dbIsNotNull !== drizzleIsNotNull;\n\n // Check if default value has changed\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 !== dbCol.COLUMN_DEFAULT;\n\n // Column needs modification if any of these changed\n if (typeChanged || nullabilityChanged || defaultChanged) {\n const type = dbCol.COLUMN_TYPE; // Use database type as source of truth\n const defaultValue = dbCol.COLUMN_DEFAULT;\n\n // Determine if we need a pre-migration for NOT NULL constraint\n let premigrationId: string | undefined = undefined;\n if (dbIsNotNull && !drizzleIsNotNull) {\n // Changing from NULL to NOT NULL - need pre-migration\n premigrationId = uuid();\n preMigrations[premigrationId] = {\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"MODIFY_NOT_NULL\",\n defaultValue: defaultValue,\n };\n }\n\n // Build DEFAULT clause if default value exists\n let defaultClause = \"\";\n if (defaultValue !== undefined && defaultValue !== null) {\n const defaultValueObj: PreMigrationNotNull = {\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"INLINE\",\n defaultValue: defaultValue,\n };\n defaultClause = ` DEFAULT ${buildDefault(defaultValueObj)}`;\n }\n\n // Generate MODIFY COLUMN statement\n const modifyStatement = `ALTER TABLE \\`${tableName}\\` MODIFY COLUMN IF EXISTS \\`${colName}\\` ${type} ${nullable}${defaultClause};`;\n\n changes.push({\n change: modifyStatement,\n premigrationId,\n });\n }\n }\n\n // Check for index changes\n const table = Object.values(schemaModule).find((t) => {\n const metadata = getTableMetadata(t);\n return metadata.tableName === tableName;\n });\n\n if (table) {\n const metadata = getTableMetadata(table);\n // First check indexes that exist in database but not in schema\n for (const [indexName, dbIndex] of Object.entries(dbTable.indexes)) {\n // Skip primary key and foreign key indexes\n if (indexName === \"PRIMARY\") {\n continue;\n }\n\n // Check if this is a foreign key index\n const isForeignKeyIndex = metadata.foreignKeys.some(\n (fk) => getForeignKeyName(fk) === indexName || compareForeignKey(fk, dbIndex),\n );\n if (isForeignKeyIndex) {\n continue;\n }\n\n // Check if this is a unique constraint\n const existsUniqIndex = metadata.uniqueConstraints.find(\n (uc) => getUniqueConstraintName(uc) === indexName,\n );\n let drizzleIndex = metadata.indexes.find((i) => getIndexName(i) === indexName);\n\n if (!drizzleIndex && existsUniqIndex) {\n drizzleIndex = existsUniqIndex as unknown as AnyIndexBuilder;\n }\n\n if (!drizzleIndex) {\n // Index exists in database but not in schema - create it\n const columns = 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}\\` (${columns});`,\n });\n continue;\n }\n\n // Check if index columns changed\n const dbColumns = dbIndex.columns.join(\", \");\n const drizzleColumns = getIndexColumns(drizzleIndex).join(\", \");\n if (\n dbColumns !== drizzleColumns ||\n dbIndex.unique !== drizzleIndex instanceof UniqueConstraintBuilder\n ) {\n // Drop and recreate index using database values\n changes.push({ change: `DROP INDEX \\`${indexName}\\` ON \\`${tableName}\\`;` });\n const columns = 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}\\` (${columns});`,\n });\n }\n }\n\n // First check foreign keys that exist in database but not in schema\n for (const [fkName, dbFK] of Object.entries(dbTable.foreignKeys)) {\n // Find if this column is referenced in Drizzle schema\n const drizzleFK = metadata.foreignKeys.find(\n (fk) =>\n getForeignKeyName(fk) === fkName ||\n compareForeignKey(fk, { columns: [dbFK.column], unique: false }),\n );\n\n if (!drizzleFK) {\n // Foreign key exists in database but not in schema - drop it\n changes.push({\n change: `ALTER TABLE \\`${tableName}\\` ADD CONSTRAINT \\`${fkName}\\` FOREIGN KEY (\\`${dbFK.column}\\`) REFERENCES \\`${dbFK.referencedTable}\\` (\\`${dbFK.referencedColumn}\\`);`,\n });\n continue;\n }\n }\n\n // Then check for new foreign keys that exist in schema but not in database\n for (const drizzleForeignKey of metadata.foreignKeys) {\n // Find if this foreign key exists in database\n const isDbFk = Object.keys(dbTable.foreignKeys).find((fk) => {\n let foreignKey = dbTable.foreignKeys[fk];\n return (\n fk === getForeignKeyName(drizzleForeignKey) ||\n compareForeignKey(drizzleForeignKey, { columns: [foreignKey.column], unique: false })\n );\n });\n\n if (!isDbFk) {\n // Foreign key exists in schema but not in database - create it\n if (drizzleForeignKey) {\n const fkName = getForeignKeyName(drizzleForeignKey);\n if (fkName) {\n changes.push({\n change: `ALTER TABLE \\`${tableName}\\` DROP FOREIGN KEY \\`${fkName}\\`;`,\n });\n } else {\n // @ts-ignore\n const columns = drizzleForeignKey.columns;\n const columnNames = columns?.length\n ? columns.map((c: any) => 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 }\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: any) => {\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 any).autoincrement,\n columnType: column.columnType,\n name: column.name,\n default: column.hasDefault ? String(column.default) : undefined,\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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { MySqlTable, TableConfig } from \"drizzle-orm/mysql-core\";\nimport { getTableMetadata, generateDropTableStatements } from \"forge-sql-orm\";\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: any) => {\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","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport dotenv from \"dotenv\";\nimport inquirer from \"inquirer\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { generateModels } from \"./actions/generate-models\";\nimport { createMigration } from \"./actions/migrations-create\";\nimport { updateMigration } from \"./actions/migrations-update\";\nimport { dropMigration } from \"./actions/migrations-drops\";\n\nconst ENV_PATH = path.resolve(process.cwd(), \".env\");\n// 🔄 Load environment variables from `.env` file\ndotenv.config({ path: ENV_PATH });\n\nconst saveEnvFile = (config: any) => {\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((acc: any, 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()}`] = 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: any,\n defaultOutput: string,\n customAskMissingParams?: (cfg: any, questions: unknown[]) => void,\n) => {\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) => !isNaN(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);\n return { ...config, ...answers, port: parseInt(config.port ?? answers.port, 10) };\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 */\nconst getConfig = async (\n cmd: any,\n defaultOutput: string,\n customConfig?: () => any,\n customAskMissingParams?: (cfg: any, questions: unknown[]) => void,\n) => {\n let config = {\n host: cmd.host || process.env.FORGE_SQL_ORM_HOST,\n port: cmd.port\n ? parseInt(cmd.port, 10)\n : process.env.FORGE_SQL_ORM_PORT\n ? parseInt(process.env.FORGE_SQL_ORM_PORT, 10)\n : undefined,\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);\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(\"--entitiesPath <string>\", \"Path to the folder containing entities\")\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(\n cmd,\n \"./database/migration\",\n () => ({\n entitiesPath: cmd.entitiesPath || process.env.FORGE_SQL_ORM_ENTITIESPATH,\n force: cmd.force || false,\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 createMigration(config);\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);\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);\n });\n\n// 🔥 Execute CLI\n program.parse(process.argv);\n"],"names":["execSync","loadMigrationVersion","generateMigrationFile","saveMigrationFiles","columns","nullable","uuid","getTableMetadata","drizzleColumns","UniqueConstraintBuilder","generateDropTableStatements","Command"],"mappings":"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"}
|
package/dist-cli/cli.mjs
CHANGED
|
@@ -784,7 +784,7 @@ const updateMigration = async (options) => {
|
|
|
784
784
|
autoincrement: column.autoincrement,
|
|
785
785
|
columnType: column.columnType,
|
|
786
786
|
name: column.name,
|
|
787
|
-
default:
|
|
787
|
+
default: column.hasDefault ? String(column.default) : void 0,
|
|
788
788
|
getSQLType: () => column.getSQLType()
|
|
789
789
|
};
|
|
790
790
|
});
|
package/dist-cli/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","sources":["../src/actions/generate-models.ts","../src/actions/migrations-create.ts","../src/actions/migrations-update.ts","../src/actions/migrations-drops.ts","../src/cli.ts"],"sourcesContent":["import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { execSync } from \"child_process\";\n\n/**\n * Options for model generation\n */\ninterface 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, any>;\n foreignKeys: Record<string, any>;\n uniqueConstraints: Record<string, any>;\n checkConstraint: Record<string, any>;\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/**\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 await 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 // Process metadata to create version map\n const metaDir = path.join(options.output, \"meta\");\n const additionalMetadata: AdditionalMetadata = {};\n\n if (fs.existsSync(metaDir)) {\n const snapshotFile = path.join(metaDir, \"0000_snapshot.json\");\n if (fs.existsSync(snapshotFile)) {\n const snapshotData = JSON.parse(fs.readFileSync(snapshotFile, \"utf-8\"));\n\n // Process each table from the snapshot\n for (const [tableName, tableData] of Object.entries(snapshotData.tables)) {\n const table = tableData as TableMetadata;\n\n // Check if table name starts with 'a_' and warn about cache\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 // Find version field in columns\n const versionField = Object.entries(table.columns).find(\n ([_, col]) => col.name.toLowerCase() === options.versionField,\n );\n\n if (versionField) {\n const [_, col] = versionField;\n const fieldType = col.type;\n const isSupportedType =\n fieldType === \"datetime\" ||\n fieldType === \"timestamp\" ||\n fieldType === \"int\" ||\n fieldType === \"number\" ||\n fieldType === \"decimal\";\n if (!col.notNull) {\n console.warn(\n `Version field \"${col.name}\" in table ${tableName} is nullable. Versioning may not work correctly.`,\n );\n } else if (!isSupportedType) {\n console.warn(\n `Version field \"${col.name}\" in table ${tableName} has unsupported type \"${fieldType}\". ` +\n `Only datetime, timestamp, int, and decimal types are supported for versioning. Versioning will be skipped.`,\n );\n } else {\n additionalMetadata[tableName] = {\n tableName,\n versionField: {\n fieldName: col.name,\n },\n };\n }\n }\n }\n }\n }\n\n // Create version metadata file\n const versionMetadataContent = `/**\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 fs.writeFileSync(path.join(options.output, \"index.ts\"), versionMetadataContent);\n\n // Replace MySQL types in the generated schema file\n const schemaPath = path.join(options.output, \"schema.ts\");\n if (fs.existsSync(schemaPath)) {\n const schemaContent = fs.readFileSync(schemaPath, \"utf-8\");\n const modifiedContent = replaceMySQLTypes(schemaContent);\n fs.writeFileSync(schemaPath, modifiedContent);\n console.log(`✅ Updated schema types in: ${schemaPath}`);\n }\n\n // Remove migration files and meta directory if they exist\n const migrationDir = path.join(options.output, \"migrations\");\n\n if (fs.existsSync(migrationDir)) {\n fs.rmSync(migrationDir, { recursive: true, force: true });\n console.log(`✅ Removed: ${migrationDir}`);\n }\n\n // Read journal and remove corresponding SQL file\n if (fs.existsSync(metaDir)) {\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\n // Remove SQL files for each entry\n for (const entry of journalData.entries) {\n const sqlFile = path.join(options.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 // Remove meta directory after processing\n fs.rmSync(metaDir, { recursive: true, force: true });\n console.log(`✅ Removed: ${metaDir}`);\n }\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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"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<any[]>(\"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 const result = rows as CreateTableRow[];\n if (result.length > 0 && result[0][\"Create Table\"]) {\n return result[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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport mysql from \"mysql2/promise\";\nimport { 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\ninterface DrizzleColumn {\n type: string;\n notNull: boolean;\n autoincrement?: boolean;\n columnType?: any;\n name: string;\n default?: string;\n getSQLType: () => string;\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 =\n preMigration.defaultValue === undefined || preMigration.defaultValue === null\n ? \"?\"\n : 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\n const updateStatement = generateUpdateStatement(preMigration, defaultValue);\n migrationLineList.push(\n `\\nmigrationRunner.enqueue(\"${versionPrefix}${index}_UPDATE_EXISTS_RECORDS\", \"${updateStatement}\")`,\n );\n\n // Step 3: Apply the MODIFY statement\n migrationLineList.push(\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/**\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\n const prevStatements = prevContent\n .split(\"\\n\")\n .filter((line) => line.includes(\".enqueue(\"))\n .map((line) => {\n const match = line.match(/\\.enqueue\\([^,]+,\\s*\"([^\"]+)\"/);\n return match ? match[1].replace(/\\s+/g, \" \").trim() : \"\";\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.includes(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\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 fcolumns.sort().join(\",\") === columns.sort().join(\",\");\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, any>,\n): {\n changes: { change: string; premigrationId?: string }[];\n preMigrations: Record<string, PreMigrationNotNull>;\n} {\n const changes: { change: string; premigrationId?: string }[] = [];\n const preMigrations: Record<string, PreMigrationNotNull> = {};\n // First check existing tables in database\n for (const [tableName, dbTable] of Object.entries(dbSchema)) {\n const drizzleColumns = drizzleSchema[tableName];\n\n if (!drizzleColumns) {\n // Table exists in database but not in schema - create it\n const columns = Object.entries(dbTable.columns)\n .map(([colName, col]) => {\n const type = col.COLUMN_TYPE;\n const nullable = col.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n const autoIncrement = col.EXTRA.includes(\"auto_increment\") ? \"AUTO_INCREMENT\" : \"\";\n return `\\`${colName}\\` ${type} ${nullable} ${autoIncrement}`.trim();\n })\n .join(\",\\n \");\n\n changes.push({ change: `CREATE TABLE if not exists \\`${tableName}\\` (\\n ${columns}\\n);` });\n\n // Create indexes for new table\n for (const [indexName, dbIndex] of Object.entries(dbTable.indexes)) {\n // Skip primary key and foreign key indexes\n if (indexName === \"PRIMARY\") {\n continue;\n }\n\n // Check if any column in this index is a foreign key\n const isForeignKeyIndex = dbIndex.columns.some((colName) => {\n const column = dbTable.columns[colName];\n return column && column.COLUMN_KEY === \"MUL\" && column.EXTRA.includes(\"foreign key\");\n });\n\n if (isForeignKeyIndex) {\n continue;\n }\n\n // Create index\n const columns = 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}\\` (${columns});`,\n });\n }\n\n // Create foreign keys for new table\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 continue;\n }\n\n // Check for column changes in existing tables\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 // Column exists in database but not in schema - create it\n const type = dbCol.COLUMN_TYPE;\n const nullable = dbCol.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n let premigrationId = nullable === \"NOT NULL\" ? uuid() : undefined;\n const defaultValue = dbCol.COLUMN_DEFAULT;\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 changes.push({\n change: `ALTER TABLE \\`${tableName}\\` ADD COLUMN IF NOT EXISTS \\`${colName}\\` ${type} ${nullable} ${\n defaultValue === undefined || defaultValue === null\n ? \"\"\n : `DEFAULT ${buildDefault({\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"INLINE\",\n defaultValue: defaultValue,\n })}`\n };`,\n premigrationId,\n });\n continue;\n }\n\n // Check for column changes (type, nullability, or default value)\n const normalizedDbType = normalizeMySQLType(dbCol.COLUMN_TYPE);\n const normalizedDrizzleType = normalizeMySQLType(drizzleCol.getSQLType());\n const nullable = dbCol.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n const dbIsNotNull = nullable === \"NOT NULL\";\n const drizzleIsNotNull = drizzleCol.notNull;\n\n // Check if type has changed\n const typeChanged = normalizedDbType !== normalizedDrizzleType;\n\n // Check if nullability has changed\n const nullabilityChanged = dbIsNotNull !== drizzleIsNotNull;\n\n // Check if default value has changed\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 !== dbCol.COLUMN_DEFAULT;\n\n // Column needs modification if any of these changed\n if (typeChanged || nullabilityChanged || defaultChanged) {\n const type = dbCol.COLUMN_TYPE; // Use database type as source of truth\n const defaultValue = dbCol.COLUMN_DEFAULT;\n\n // Determine if we need a pre-migration for NOT NULL constraint\n let premigrationId: string | undefined = undefined;\n if (dbIsNotNull && !drizzleIsNotNull) {\n // Changing from NULL to NOT NULL - need pre-migration\n premigrationId = uuid();\n preMigrations[premigrationId] = {\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"MODIFY_NOT_NULL\",\n defaultValue: defaultValue,\n };\n }\n\n // Build DEFAULT clause if default value exists\n let defaultClause = \"\";\n if (defaultValue !== undefined && defaultValue !== null) {\n const defaultValueObj: PreMigrationNotNull = {\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"INLINE\",\n defaultValue: defaultValue,\n };\n defaultClause = ` DEFAULT ${buildDefault(defaultValueObj)}`;\n }\n\n // Generate MODIFY COLUMN statement\n const modifyStatement = `ALTER TABLE \\`${tableName}\\` MODIFY COLUMN IF EXISTS \\`${colName}\\` ${type} ${nullable}${defaultClause};`;\n\n changes.push({\n change: modifyStatement,\n premigrationId,\n });\n }\n }\n\n // Check for index changes\n const table = Object.values(schemaModule).find((t) => {\n const metadata = getTableMetadata(t);\n return metadata.tableName === tableName;\n });\n\n if (table) {\n const metadata = getTableMetadata(table);\n // First check indexes that exist in database but not in schema\n for (const [indexName, dbIndex] of Object.entries(dbTable.indexes)) {\n // Skip primary key and foreign key indexes\n if (indexName === \"PRIMARY\") {\n continue;\n }\n\n // Check if this is a foreign key index\n const isForeignKeyIndex = metadata.foreignKeys.some(\n (fk) => getForeignKeyName(fk) === indexName || compareForeignKey(fk, dbIndex),\n );\n if (isForeignKeyIndex) {\n continue;\n }\n\n // Check if this is a unique constraint\n const existsUniqIndex = metadata.uniqueConstraints.find(\n (uc) => getUniqueConstraintName(uc) === indexName,\n );\n let drizzleIndex = metadata.indexes.find((i) => getIndexName(i) === indexName);\n\n if (!drizzleIndex && existsUniqIndex) {\n drizzleIndex = existsUniqIndex as unknown as AnyIndexBuilder;\n }\n\n if (!drizzleIndex) {\n // Index exists in database but not in schema - create it\n const columns = 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}\\` (${columns});`,\n });\n continue;\n }\n\n // Check if index columns changed\n const dbColumns = dbIndex.columns.join(\", \");\n const drizzleColumns = getIndexColumns(drizzleIndex).join(\", \");\n if (\n dbColumns !== drizzleColumns ||\n dbIndex.unique !== drizzleIndex instanceof UniqueConstraintBuilder\n ) {\n // Drop and recreate index using database values\n changes.push({ change: `DROP INDEX \\`${indexName}\\` ON \\`${tableName}\\`;` });\n const columns = 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}\\` (${columns});`,\n });\n }\n }\n\n // First check foreign keys that exist in database but not in schema\n for (const [fkName, dbFK] of Object.entries(dbTable.foreignKeys)) {\n // Find if this column is referenced in Drizzle schema\n const drizzleFK = metadata.foreignKeys.find(\n (fk) =>\n getForeignKeyName(fk) === fkName ||\n compareForeignKey(fk, { columns: [dbFK.column], unique: false }),\n );\n\n if (!drizzleFK) {\n // Foreign key exists in database but not in schema - drop it\n changes.push({\n change: `ALTER TABLE \\`${tableName}\\` ADD CONSTRAINT \\`${fkName}\\` FOREIGN KEY (\\`${dbFK.column}\\`) REFERENCES \\`${dbFK.referencedTable}\\` (\\`${dbFK.referencedColumn}\\`);`,\n });\n continue;\n }\n }\n\n // Then check for new foreign keys that exist in schema but not in database\n for (const drizzleForeignKey of metadata.foreignKeys) {\n // Find if this foreign key exists in database\n const isDbFk = Object.keys(dbTable.foreignKeys).find((fk) => {\n let foreignKey = dbTable.foreignKeys[fk];\n return (\n fk === getForeignKeyName(drizzleForeignKey) ||\n compareForeignKey(drizzleForeignKey, { columns: [foreignKey.column], unique: false })\n );\n });\n\n if (!isDbFk) {\n // Foreign key exists in schema but not in database - create it\n if (drizzleForeignKey) {\n const fkName = getForeignKeyName(drizzleForeignKey);\n if (fkName) {\n changes.push({\n change: `ALTER TABLE \\`${tableName}\\` DROP FOREIGN KEY \\`${fkName}\\`;`,\n });\n } else {\n // @ts-ignore\n const columns = drizzleForeignKey.columns;\n const columnNames = columns?.length\n ? columns.map((c: any) => 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 }\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: any) => {\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 any).autoincrement,\n columnType: column.columnType,\n name: column.name,\n default: metadata.columns.email.hasDefault ? String(column.default) : undefined,\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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { MySqlTable, TableConfig } from \"drizzle-orm/mysql-core\";\nimport { getTableMetadata, generateDropTableStatements } from \"forge-sql-orm\";\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: any) => {\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","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport dotenv from \"dotenv\";\nimport inquirer from \"inquirer\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { generateModels } from \"./actions/generate-models\";\nimport { createMigration } from \"./actions/migrations-create\";\nimport { updateMigration } from \"./actions/migrations-update\";\nimport { dropMigration } from \"./actions/migrations-drops\";\n\nconst ENV_PATH = path.resolve(process.cwd(), \".env\");\n// 🔄 Load environment variables from `.env` file\ndotenv.config({ path: ENV_PATH });\n\nconst saveEnvFile = (config: any) => {\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((acc: any, 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()}`] = 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: any,\n defaultOutput: string,\n customAskMissingParams?: (cfg: any, questions: unknown[]) => void,\n) => {\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) => !isNaN(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);\n return { ...config, ...answers, port: parseInt(config.port ?? answers.port, 10) };\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 */\nconst getConfig = async (\n cmd: any,\n defaultOutput: string,\n customConfig?: () => any,\n customAskMissingParams?: (cfg: any, questions: unknown[]) => void,\n) => {\n let config = {\n host: cmd.host || process.env.FORGE_SQL_ORM_HOST,\n port: cmd.port\n ? parseInt(cmd.port, 10)\n : process.env.FORGE_SQL_ORM_PORT\n ? parseInt(process.env.FORGE_SQL_ORM_PORT, 10)\n : undefined,\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);\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(\"--entitiesPath <string>\", \"Path to the folder containing entities\")\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(\n cmd,\n \"./database/migration\",\n () => ({\n entitiesPath: cmd.entitiesPath || process.env.FORGE_SQL_ORM_ENTITIESPATH,\n force: cmd.force || false,\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 createMigration(config);\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);\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);\n });\n\n// 🔥 Execute CLI\n program.parse(process.argv);\n"],"names":["loadMigrationVersion","generateMigrationFile","saveMigrationFiles","columns","nullable","uuid","drizzleColumns"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","sources":["../src/actions/generate-models.ts","../src/actions/migrations-create.ts","../src/actions/migrations-update.ts","../src/actions/migrations-drops.ts","../src/cli.ts"],"sourcesContent":["import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { execSync } from \"child_process\";\n\n/**\n * Options for model generation\n */\ninterface 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, any>;\n foreignKeys: Record<string, any>;\n uniqueConstraints: Record<string, any>;\n checkConstraint: Record<string, any>;\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/**\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 await 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 // Process metadata to create version map\n const metaDir = path.join(options.output, \"meta\");\n const additionalMetadata: AdditionalMetadata = {};\n\n if (fs.existsSync(metaDir)) {\n const snapshotFile = path.join(metaDir, \"0000_snapshot.json\");\n if (fs.existsSync(snapshotFile)) {\n const snapshotData = JSON.parse(fs.readFileSync(snapshotFile, \"utf-8\"));\n\n // Process each table from the snapshot\n for (const [tableName, tableData] of Object.entries(snapshotData.tables)) {\n const table = tableData as TableMetadata;\n\n // Check if table name starts with 'a_' and warn about cache\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 // Find version field in columns\n const versionField = Object.entries(table.columns).find(\n ([_, col]) => col.name.toLowerCase() === options.versionField,\n );\n\n if (versionField) {\n const [_, col] = versionField;\n const fieldType = col.type;\n const isSupportedType =\n fieldType === \"datetime\" ||\n fieldType === \"timestamp\" ||\n fieldType === \"int\" ||\n fieldType === \"number\" ||\n fieldType === \"decimal\";\n if (!col.notNull) {\n console.warn(\n `Version field \"${col.name}\" in table ${tableName} is nullable. Versioning may not work correctly.`,\n );\n } else if (!isSupportedType) {\n console.warn(\n `Version field \"${col.name}\" in table ${tableName} has unsupported type \"${fieldType}\". ` +\n `Only datetime, timestamp, int, and decimal types are supported for versioning. Versioning will be skipped.`,\n );\n } else {\n additionalMetadata[tableName] = {\n tableName,\n versionField: {\n fieldName: col.name,\n },\n };\n }\n }\n }\n }\n }\n\n // Create version metadata file\n const versionMetadataContent = `/**\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 fs.writeFileSync(path.join(options.output, \"index.ts\"), versionMetadataContent);\n\n // Replace MySQL types in the generated schema file\n const schemaPath = path.join(options.output, \"schema.ts\");\n if (fs.existsSync(schemaPath)) {\n const schemaContent = fs.readFileSync(schemaPath, \"utf-8\");\n const modifiedContent = replaceMySQLTypes(schemaContent);\n fs.writeFileSync(schemaPath, modifiedContent);\n console.log(`✅ Updated schema types in: ${schemaPath}`);\n }\n\n // Remove migration files and meta directory if they exist\n const migrationDir = path.join(options.output, \"migrations\");\n\n if (fs.existsSync(migrationDir)) {\n fs.rmSync(migrationDir, { recursive: true, force: true });\n console.log(`✅ Removed: ${migrationDir}`);\n }\n\n // Read journal and remove corresponding SQL file\n if (fs.existsSync(metaDir)) {\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\n // Remove SQL files for each entry\n for (const entry of journalData.entries) {\n const sqlFile = path.join(options.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 // Remove meta directory after processing\n fs.rmSync(metaDir, { recursive: true, force: true });\n console.log(`✅ Removed: ${metaDir}`);\n }\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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"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<any[]>(\"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 const result = rows as CreateTableRow[];\n if (result.length > 0 && result[0][\"Create Table\"]) {\n return result[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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport mysql from \"mysql2/promise\";\nimport { 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\ninterface DrizzleColumn {\n type: string;\n notNull: boolean;\n autoincrement?: boolean;\n columnType?: any;\n name: string;\n default?: string;\n getSQLType: () => string;\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 =\n preMigration.defaultValue === undefined || preMigration.defaultValue === null\n ? \"?\"\n : 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\n const updateStatement = generateUpdateStatement(preMigration, defaultValue);\n migrationLineList.push(\n `\\nmigrationRunner.enqueue(\"${versionPrefix}${index}_UPDATE_EXISTS_RECORDS\", \"${updateStatement}\")`,\n );\n\n // Step 3: Apply the MODIFY statement\n migrationLineList.push(\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/**\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\n const prevStatements = prevContent\n .split(\"\\n\")\n .filter((line) => line.includes(\".enqueue(\"))\n .map((line) => {\n const match = line.match(/\\.enqueue\\([^,]+,\\s*\"([^\"]+)\"/);\n return match ? match[1].replace(/\\s+/g, \" \").trim() : \"\";\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.includes(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\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 fcolumns.sort().join(\",\") === columns.sort().join(\",\");\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, any>,\n): {\n changes: { change: string; premigrationId?: string }[];\n preMigrations: Record<string, PreMigrationNotNull>;\n} {\n const changes: { change: string; premigrationId?: string }[] = [];\n const preMigrations: Record<string, PreMigrationNotNull> = {};\n // First check existing tables in database\n for (const [tableName, dbTable] of Object.entries(dbSchema)) {\n const drizzleColumns = drizzleSchema[tableName];\n\n if (!drizzleColumns) {\n // Table exists in database but not in schema - create it\n const columns = Object.entries(dbTable.columns)\n .map(([colName, col]) => {\n const type = col.COLUMN_TYPE;\n const nullable = col.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n const autoIncrement = col.EXTRA.includes(\"auto_increment\") ? \"AUTO_INCREMENT\" : \"\";\n return `\\`${colName}\\` ${type} ${nullable} ${autoIncrement}`.trim();\n })\n .join(\",\\n \");\n\n changes.push({ change: `CREATE TABLE if not exists \\`${tableName}\\` (\\n ${columns}\\n);` });\n\n // Create indexes for new table\n for (const [indexName, dbIndex] of Object.entries(dbTable.indexes)) {\n // Skip primary key and foreign key indexes\n if (indexName === \"PRIMARY\") {\n continue;\n }\n\n // Check if any column in this index is a foreign key\n const isForeignKeyIndex = dbIndex.columns.some((colName) => {\n const column = dbTable.columns[colName];\n return column && column.COLUMN_KEY === \"MUL\" && column.EXTRA.includes(\"foreign key\");\n });\n\n if (isForeignKeyIndex) {\n continue;\n }\n\n // Create index\n const columns = 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}\\` (${columns});`,\n });\n }\n\n // Create foreign keys for new table\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 continue;\n }\n\n // Check for column changes in existing tables\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 // Column exists in database but not in schema - create it\n const type = dbCol.COLUMN_TYPE;\n const nullable = dbCol.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n let premigrationId = nullable === \"NOT NULL\" ? uuid() : undefined;\n const defaultValue = dbCol.COLUMN_DEFAULT;\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 changes.push({\n change: `ALTER TABLE \\`${tableName}\\` ADD COLUMN IF NOT EXISTS \\`${colName}\\` ${type} ${nullable} ${\n defaultValue === undefined || defaultValue === null\n ? \"\"\n : `DEFAULT ${buildDefault({\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"INLINE\",\n defaultValue: defaultValue,\n })}`\n };`,\n premigrationId,\n });\n continue;\n }\n\n // Check for column changes (type, nullability, or default value)\n const normalizedDbType = normalizeMySQLType(dbCol.COLUMN_TYPE);\n const normalizedDrizzleType = normalizeMySQLType(drizzleCol.getSQLType());\n const nullable = dbCol.IS_NULLABLE === \"YES\" ? \"NULL\" : \"NOT NULL\";\n const dbIsNotNull = nullable === \"NOT NULL\";\n const drizzleIsNotNull = drizzleCol.notNull;\n\n // Check if type has changed\n const typeChanged = normalizedDbType !== normalizedDrizzleType;\n\n // Check if nullability has changed\n const nullabilityChanged = dbIsNotNull !== drizzleIsNotNull;\n\n // Check if default value has changed\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 !== dbCol.COLUMN_DEFAULT;\n\n // Column needs modification if any of these changed\n if (typeChanged || nullabilityChanged || defaultChanged) {\n const type = dbCol.COLUMN_TYPE; // Use database type as source of truth\n const defaultValue = dbCol.COLUMN_DEFAULT;\n\n // Determine if we need a pre-migration for NOT NULL constraint\n let premigrationId: string | undefined = undefined;\n if (dbIsNotNull && !drizzleIsNotNull) {\n // Changing from NULL to NOT NULL - need pre-migration\n premigrationId = uuid();\n preMigrations[premigrationId] = {\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"MODIFY_NOT_NULL\",\n defaultValue: defaultValue,\n };\n }\n\n // Build DEFAULT clause if default value exists\n let defaultClause = \"\";\n if (defaultValue !== undefined && defaultValue !== null) {\n const defaultValueObj: PreMigrationNotNull = {\n tableName,\n dbTable,\n colName,\n type,\n migrationType: \"INLINE\",\n defaultValue: defaultValue,\n };\n defaultClause = ` DEFAULT ${buildDefault(defaultValueObj)}`;\n }\n\n // Generate MODIFY COLUMN statement\n const modifyStatement = `ALTER TABLE \\`${tableName}\\` MODIFY COLUMN IF EXISTS \\`${colName}\\` ${type} ${nullable}${defaultClause};`;\n\n changes.push({\n change: modifyStatement,\n premigrationId,\n });\n }\n }\n\n // Check for index changes\n const table = Object.values(schemaModule).find((t) => {\n const metadata = getTableMetadata(t);\n return metadata.tableName === tableName;\n });\n\n if (table) {\n const metadata = getTableMetadata(table);\n // First check indexes that exist in database but not in schema\n for (const [indexName, dbIndex] of Object.entries(dbTable.indexes)) {\n // Skip primary key and foreign key indexes\n if (indexName === \"PRIMARY\") {\n continue;\n }\n\n // Check if this is a foreign key index\n const isForeignKeyIndex = metadata.foreignKeys.some(\n (fk) => getForeignKeyName(fk) === indexName || compareForeignKey(fk, dbIndex),\n );\n if (isForeignKeyIndex) {\n continue;\n }\n\n // Check if this is a unique constraint\n const existsUniqIndex = metadata.uniqueConstraints.find(\n (uc) => getUniqueConstraintName(uc) === indexName,\n );\n let drizzleIndex = metadata.indexes.find((i) => getIndexName(i) === indexName);\n\n if (!drizzleIndex && existsUniqIndex) {\n drizzleIndex = existsUniqIndex as unknown as AnyIndexBuilder;\n }\n\n if (!drizzleIndex) {\n // Index exists in database but not in schema - create it\n const columns = 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}\\` (${columns});`,\n });\n continue;\n }\n\n // Check if index columns changed\n const dbColumns = dbIndex.columns.join(\", \");\n const drizzleColumns = getIndexColumns(drizzleIndex).join(\", \");\n if (\n dbColumns !== drizzleColumns ||\n dbIndex.unique !== drizzleIndex instanceof UniqueConstraintBuilder\n ) {\n // Drop and recreate index using database values\n changes.push({ change: `DROP INDEX \\`${indexName}\\` ON \\`${tableName}\\`;` });\n const columns = 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}\\` (${columns});`,\n });\n }\n }\n\n // First check foreign keys that exist in database but not in schema\n for (const [fkName, dbFK] of Object.entries(dbTable.foreignKeys)) {\n // Find if this column is referenced in Drizzle schema\n const drizzleFK = metadata.foreignKeys.find(\n (fk) =>\n getForeignKeyName(fk) === fkName ||\n compareForeignKey(fk, { columns: [dbFK.column], unique: false }),\n );\n\n if (!drizzleFK) {\n // Foreign key exists in database but not in schema - drop it\n changes.push({\n change: `ALTER TABLE \\`${tableName}\\` ADD CONSTRAINT \\`${fkName}\\` FOREIGN KEY (\\`${dbFK.column}\\`) REFERENCES \\`${dbFK.referencedTable}\\` (\\`${dbFK.referencedColumn}\\`);`,\n });\n continue;\n }\n }\n\n // Then check for new foreign keys that exist in schema but not in database\n for (const drizzleForeignKey of metadata.foreignKeys) {\n // Find if this foreign key exists in database\n const isDbFk = Object.keys(dbTable.foreignKeys).find((fk) => {\n let foreignKey = dbTable.foreignKeys[fk];\n return (\n fk === getForeignKeyName(drizzleForeignKey) ||\n compareForeignKey(drizzleForeignKey, { columns: [foreignKey.column], unique: false })\n );\n });\n\n if (!isDbFk) {\n // Foreign key exists in schema but not in database - create it\n if (drizzleForeignKey) {\n const fkName = getForeignKeyName(drizzleForeignKey);\n if (fkName) {\n changes.push({\n change: `ALTER TABLE \\`${tableName}\\` DROP FOREIGN KEY \\`${fkName}\\`;`,\n });\n } else {\n // @ts-ignore\n const columns = drizzleForeignKey.columns;\n const columnNames = columns?.length\n ? columns.map((c: any) => 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 }\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: any) => {\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 any).autoincrement,\n columnType: column.columnType,\n name: column.name,\n default: column.hasDefault ? String(column.default) : undefined,\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","import \"reflect-metadata\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { MySqlTable, TableConfig } from \"drizzle-orm/mysql-core\";\nimport { getTableMetadata, generateDropTableStatements } from \"forge-sql-orm\";\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: any) => {\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","#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport dotenv from \"dotenv\";\nimport inquirer from \"inquirer\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { generateModels } from \"./actions/generate-models\";\nimport { createMigration } from \"./actions/migrations-create\";\nimport { updateMigration } from \"./actions/migrations-update\";\nimport { dropMigration } from \"./actions/migrations-drops\";\n\nconst ENV_PATH = path.resolve(process.cwd(), \".env\");\n// 🔄 Load environment variables from `.env` file\ndotenv.config({ path: ENV_PATH });\n\nconst saveEnvFile = (config: any) => {\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((acc: any, 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()}`] = 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: any,\n defaultOutput: string,\n customAskMissingParams?: (cfg: any, questions: unknown[]) => void,\n) => {\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) => !isNaN(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);\n return { ...config, ...answers, port: parseInt(config.port ?? answers.port, 10) };\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 */\nconst getConfig = async (\n cmd: any,\n defaultOutput: string,\n customConfig?: () => any,\n customAskMissingParams?: (cfg: any, questions: unknown[]) => void,\n) => {\n let config = {\n host: cmd.host || process.env.FORGE_SQL_ORM_HOST,\n port: cmd.port\n ? parseInt(cmd.port, 10)\n : process.env.FORGE_SQL_ORM_PORT\n ? parseInt(process.env.FORGE_SQL_ORM_PORT, 10)\n : undefined,\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);\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(\"--entitiesPath <string>\", \"Path to the folder containing entities\")\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(\n cmd,\n \"./database/migration\",\n () => ({\n entitiesPath: cmd.entitiesPath || process.env.FORGE_SQL_ORM_ENTITIESPATH,\n force: cmd.force || false,\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 createMigration(config);\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);\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);\n });\n\n// 🔥 Execute CLI\n program.parse(process.argv);\n"],"names":["loadMigrationVersion","generateMigrationFile","saveMigrationFiles","columns","nullable","uuid","drizzleColumns"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -902,7 +902,7 @@ export const updateMigration = async (options: any) => {
|
|
|
902
902
|
autoincrement: (column as any).autoincrement,
|
|
903
903
|
columnType: column.columnType,
|
|
904
904
|
name: column.name,
|
|
905
|
-
default:
|
|
905
|
+
default: column.hasDefault ? String(column.default) : undefined,
|
|
906
906
|
getSQLType: () => column.getSQLType(),
|
|
907
907
|
};
|
|
908
908
|
});
|