forge-sql-orm-cli 2.1.14 → 2.1.16

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.
@@ -8,6 +8,7 @@ import { getTableMetadata } from "forge-sql-orm";
8
8
  import { AnyIndexBuilder } from "drizzle-orm/mysql-core/indexes";
9
9
  import { ForeignKeyBuilder } from "drizzle-orm/mysql-core/foreign-keys";
10
10
  import { UniqueConstraintBuilder } from "drizzle-orm/mysql-core/unique-constraint";
11
+ import { v4 as uuid } from "uuid";
11
12
 
12
13
  interface DrizzleColumn {
13
14
  type: string;
@@ -15,6 +16,7 @@ interface DrizzleColumn {
15
16
  autoincrement?: boolean;
16
17
  columnType?: any;
17
18
  name: string;
19
+ default?: string;
18
20
  getSQLType: () => string;
19
21
  }
20
22
 
@@ -71,26 +73,208 @@ interface DatabaseSchema {
71
73
  [tableName: string]: TableSchema;
72
74
  }
73
75
 
76
+ type PreMigrationNotNull = {
77
+ tableName: string;
78
+ dbTable: TableSchema;
79
+ colName: string;
80
+ type: string;
81
+ migrationType: "NEW_FIELD_NOT_NULL" | "MODIFY_NOT_NULL" | "INLINE";
82
+ defaultValue: string;
83
+ };
84
+
85
+ function buildDefault(preMigration: PreMigrationNotNull): string {
86
+ const def = preMigration.defaultValue;
87
+ const type = preMigration.type.toLowerCase();
88
+
89
+ // No default defined
90
+ if (def === undefined || def === null) {
91
+ return "";
92
+ }
93
+
94
+ // Empty string default → DEFAULT ''
95
+ if (def === "") {
96
+ return `''`;
97
+ }
98
+
99
+ // Types that must be quoted
100
+ const stringTypes = new Set([
101
+ "char",
102
+ "varchar",
103
+ "text",
104
+ "tinytext",
105
+ "mediumtext",
106
+ "longtext",
107
+ "enum",
108
+ "set",
109
+ "binary",
110
+ "varbinary",
111
+ "blob",
112
+ ]);
113
+
114
+ // Numeric types that accept numeric literals
115
+ const numericTypes = new Set([
116
+ "tinyint",
117
+ "smallint",
118
+ "mediumint",
119
+ "int",
120
+ "bigint",
121
+ "decimal",
122
+ "float",
123
+ "double",
124
+ "bit",
125
+ ]);
126
+
127
+ // Check if default value is a numeric literal
128
+ const isNumericLiteral = /^[+-]?\d+(\.\d+)?$/.test(def);
129
+
130
+ // Numeric types → DEFAULT 123 (no quotes)
131
+ if (numericTypes.has(type) && isNumericLiteral) {
132
+ return `${def}`;
133
+ }
134
+
135
+ // String types → DEFAULT 'value'
136
+ if (stringTypes.has(type)) {
137
+ // Double escape single quotes
138
+ const escaped = def.replace(/'/g, "''");
139
+ return `'${escaped}'`;
140
+ }
141
+
142
+ // Other types: treat default as an expression
143
+ // e.g. DEFAULT CURRENT_TIMESTAMP, DEFAULT (uuid()), DEFAULT now()
144
+ return `${def}`;
145
+ }
146
+
147
+ /**
148
+ * Generates warning message for missing default value
149
+ */
150
+ function generateWarningMessage(tableName: string, colName: string, version: number): string {
151
+ return (
152
+ `⚠️ WARNING: Field \`${tableName}\`.\`${colName}\` requires a default value for existing NULL records.\n` +
153
+ ` Action required in migration file: migrationV${version}.ts\n` +
154
+ ` Find the line with: UPDATE \`${tableName}\` SET \`${colName}\` = ?\n` +
155
+ ` Replace '?' with an actual value (e.g., '' for strings, 0 for numbers, '1970-01-01' for dates)\n` +
156
+ ` OR remove this migration if it's not needed.`
157
+ );
158
+ }
159
+
160
+ /**
161
+ * Handles warning for missing default value
162
+ */
163
+ function handleMissingDefaultValue(
164
+ preMigration: PreMigrationNotNull,
165
+ version: number,
166
+ migrationLineList: string[],
167
+ ): void {
168
+ const warningMsg = generateWarningMessage(preMigration.tableName, preMigration.colName, version);
169
+ console.warn(warningMsg);
170
+ migrationLineList.push(`console.error(${JSON.stringify(warningMsg)});`);
171
+ }
172
+
173
+ /**
174
+ * Gets the default value for UPDATE statement
175
+ */
176
+ function getUpdateDefaultValue(preMigration: PreMigrationNotNull, defaultValue: string): string {
177
+ return defaultValue === "?" ? defaultValue : buildDefault(preMigration);
178
+ }
179
+
180
+ /**
181
+ * Generates UPDATE statement for existing NULL records
182
+ */
183
+ function generateUpdateStatement(preMigration: PreMigrationNotNull, defaultValue: string): string {
184
+ const updateValue = getUpdateDefaultValue(preMigration, defaultValue);
185
+ return `UPDATE \`${preMigration.tableName}\` SET \`${preMigration.colName}\` = ${updateValue} WHERE \`${preMigration.colName}\` IS NULL`;
186
+ }
187
+
74
188
  /**
75
189
  * Generates a migration file using the provided SQL statements.
76
190
  * @param createStatements - Array of SQL statements.
77
191
  * @param version - Migration version number.
78
192
  * @returns TypeScript migration file content.
79
193
  */
80
- function generateMigrationFile(createStatements: string[], version: number): string {
194
+ function generateMigrationFile(
195
+ createStatements: {
196
+ changes: { change: string; premigrationId?: string }[];
197
+ preMigrations: Record<string, PreMigrationNotNull>;
198
+ },
199
+ version: number,
200
+ ): string {
81
201
  const versionPrefix = `v${version}_MIGRATION`;
202
+ const migrationLineList: string[] = [];
82
203
 
83
- // Clean each SQL statement and generate migration lines with .enqueue()
84
- const migrationLines = createStatements
85
- .map((stmt, index) => ` .enqueue("${versionPrefix}${index}", "${stmt}")`)
86
- .join("\n");
204
+ createStatements.changes.forEach((change, index) => {
205
+ if (!change.premigrationId) {
206
+ // Regular change without pre-migration
207
+ migrationLineList.push(
208
+ `\nmigrationRunner.enqueue("${versionPrefix}${index}", "${change.change}")`,
209
+ );
210
+ return;
211
+ }
212
+
213
+ const preMigration = createStatements.preMigrations[change.premigrationId];
214
+ if (!preMigration) {
215
+ // Pre-migration ID exists but pre-migration not found
216
+ migrationLineList.push(
217
+ `\nmigrationRunner.enqueue("${versionPrefix}${index}", "${change.change}")`,
218
+ );
219
+ return;
220
+ }
221
+
222
+ const defaultValue =
223
+ preMigration.defaultValue === undefined || preMigration.defaultValue === null
224
+ ? "?"
225
+ : preMigration.defaultValue;
226
+ const needsWarning = defaultValue === "?";
227
+
228
+ if (preMigration.migrationType === "NEW_FIELD_NOT_NULL") {
229
+ // Step 1: Add column as NULL
230
+ const addColumnStatement = change.change.replace("NOT NULL", "NULL");
231
+ migrationLineList.push(
232
+ `\nmigrationRunner.enqueue("${versionPrefix}${index}_NULLABLE", "${addColumnStatement}");`,
233
+ );
234
+
235
+ // Step 2: Warning if default value is missing
236
+ if (needsWarning) {
237
+ handleMissingDefaultValue(preMigration, version, migrationLineList);
238
+ }
239
+
240
+ // Step 3: Update existing NULL records
241
+ const updateStatement = generateUpdateStatement(preMigration, defaultValue);
242
+ migrationLineList.push(
243
+ `\nmigrationRunner.enqueue("${versionPrefix}${index}_UPDATE_EXISTS_RECORDS", "${updateStatement}");`,
244
+ );
245
+
246
+ // Step 4: Modify column to NOT NULL
247
+ const defaultClause = defaultValue === "?" ? "" : ` DEFAULT ${buildDefault(preMigration)}`;
248
+ const modifyStatement = `ALTER TABLE \`${preMigration.tableName}\` MODIFY COLUMN IF EXISTS \`${preMigration.colName}\` ${preMigration.type} NOT NULL${defaultClause};`;
249
+ migrationLineList.push(
250
+ `\nmigrationRunner.enqueue("${versionPrefix}${index}", "${modifyStatement}");`,
251
+ );
252
+ } else if (preMigration.migrationType === "MODIFY_NOT_NULL") {
253
+ // Step 1: Warning if default value is missing
254
+ if (needsWarning) {
255
+ handleMissingDefaultValue(preMigration, version, migrationLineList);
256
+ }
257
+
258
+ // Step 2: Update existing NULL records
259
+ const updateStatement = generateUpdateStatement(preMigration, defaultValue);
260
+ migrationLineList.push(
261
+ `\nmigrationRunner.enqueue("${versionPrefix}${index}_UPDATE_EXISTS_RECORDS", "${updateStatement}")`,
262
+ );
263
+
264
+ // Step 3: Apply the MODIFY statement
265
+ migrationLineList.push(
266
+ `\nmigrationRunner.enqueue("${versionPrefix}${index}", "${change.change}")`,
267
+ );
268
+ }
269
+ });
270
+
271
+ const migrationLines = migrationLineList.join("\n");
87
272
 
88
- // Migration template
89
273
  return `import { MigrationRunner } from "@forge/sql/out/migration";
90
274
 
91
- export default (migrationRunner: MigrationRunner): MigrationRunner => {
92
- return migrationRunner
275
+ export default (migrationRunner: MigrationRunner): MigrationRunner => {
93
276
  ${migrationLines};
277
+ return migrationRunner;
94
278
  };`;
95
279
  }
96
280
 
@@ -102,14 +286,26 @@ ${migrationLines};
102
286
  * @returns Array of SQL statements that don't exist in previous migration
103
287
  */
104
288
  function filterWithPreviousMigration(
105
- newStatements: string[],
289
+ newStatements: {
290
+ changes: { change: string; premigrationId?: string }[];
291
+ preMigrations: Record<string, PreMigrationNotNull>;
292
+ },
106
293
  prevVersion: number,
107
294
  outputDir: string,
108
- ): string[] {
295
+ ): {
296
+ changes: { change: string; premigrationId?: string }[];
297
+ preMigrations: Record<string, PreMigrationNotNull>;
298
+ } {
109
299
  const prevMigrationPath = path.join(outputDir, `migrationV${prevVersion}.ts`);
110
300
 
111
301
  if (!fs.existsSync(prevMigrationPath)) {
112
- return newStatements.map((s) => s.replace(/\s+/g, " "));
302
+ return {
303
+ changes: newStatements.changes.map((s) => ({
304
+ change: s.change.replace(/\s+/g, " "),
305
+ premigrationId: s.premigrationId,
306
+ })),
307
+ preMigrations: newStatements.preMigrations,
308
+ };
113
309
  }
114
310
 
115
311
  // Read previous migration file
@@ -125,9 +321,12 @@ function filterWithPreviousMigration(
125
321
  });
126
322
 
127
323
  // Filter out statements that already exist in previous migration
128
- return newStatements
129
- .filter((s) => !prevStatements.includes(s.replace(/\s+/g, " ")))
130
- .map((s) => s.replace(/\s+/g, " "));
324
+ return {
325
+ preMigrations: newStatements.preMigrations,
326
+ changes: newStatements.changes
327
+ .filter((s) => !prevStatements.includes(s.change.replace(/\s+/g, " ")))
328
+ .map((s) => ({ change: s.change.replace(/\s+/g, " "), premigrationId: s.premigrationId })),
329
+ };
131
330
  }
132
331
 
133
332
  /**
@@ -152,23 +351,26 @@ function saveMigrationFiles(migrationCode: string, version: number, outputDir: s
152
351
  // Write the migration count file
153
352
  fs.writeFileSync(migrationCountPath, `export const MIGRATION_VERSION = ${version};`);
154
353
 
155
- // Generate the migration index file
354
+ // Generate the migration index file with static imports
355
+ const importLines: string[] = [];
356
+ const callLines: string[] = [];
357
+
358
+ for (let i = 1; i <= version; i++) {
359
+ importLines.push(`import migrationV${i} from "./migrationV${i}";`);
360
+ callLines.push(` migrationV${i}(migrationRunner);`);
361
+ }
362
+
156
363
  const indexFileContent = `import { MigrationRunner } from "@forge/sql/out/migration";
157
- import { MIGRATION_VERSION } from "./migrationCount";
364
+ ${importLines.join("\n")}
158
365
 
159
366
  export type MigrationType = (
160
367
  migrationRunner: MigrationRunner,
161
368
  ) => MigrationRunner;
162
369
 
163
- export default async (
370
+ export default (
164
371
  migrationRunner: MigrationRunner,
165
- ): Promise<MigrationRunner> => {
166
- for (let i = 1; i <= MIGRATION_VERSION; i++) {
167
- const migrations = (await import(\`./migrationV\${i}\`)) as {
168
- default: MigrationType;
169
- };
170
- migrations.default(migrationRunner);
171
- }
372
+ ): MigrationRunner => {
373
+ ${callLines.join("\n")}
172
374
  return migrationRunner;
173
375
  };`;
174
376
 
@@ -218,7 +420,7 @@ async function getDatabaseSchema(
218
420
  // Get columns
219
421
  const [columns] = await connection.execute<DatabaseColumn[]>(
220
422
  `
221
- SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA
423
+ SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT
222
424
  FROM INFORMATION_SCHEMA.COLUMNS
223
425
  WHERE TABLE_SCHEMA = ?
224
426
  `,
@@ -366,9 +568,12 @@ function generateSchemaChanges(
366
568
  drizzleSchema: DrizzleSchema,
367
569
  dbSchema: DatabaseSchema,
368
570
  schemaModule: Record<string, any>,
369
- ): string[] {
370
- const changes: string[] = [];
371
-
571
+ ): {
572
+ changes: { change: string; premigrationId?: string }[];
573
+ preMigrations: Record<string, PreMigrationNotNull>;
574
+ } {
575
+ const changes: { change: string; premigrationId?: string }[] = [];
576
+ const preMigrations: Record<string, PreMigrationNotNull> = {};
372
577
  // First check existing tables in database
373
578
  for (const [tableName, dbTable] of Object.entries(dbSchema)) {
374
579
  const drizzleColumns = drizzleSchema[tableName];
@@ -384,7 +589,7 @@ function generateSchemaChanges(
384
589
  })
385
590
  .join(",\n ");
386
591
 
387
- changes.push(`CREATE TABLE if not exists \`${tableName}\` (\n ${columns}\n);`);
592
+ changes.push({ change: `CREATE TABLE if not exists \`${tableName}\` (\n ${columns}\n);` });
388
593
 
389
594
  // Create indexes for new table
390
595
  for (const [indexName, dbIndex] of Object.entries(dbTable.indexes)) {
@@ -406,16 +611,16 @@ function generateSchemaChanges(
406
611
  // Create index
407
612
  const columns = dbIndex.columns.map((col) => `\`${col}\``).join(", ");
408
613
  const unique = dbIndex.unique ? "UNIQUE " : "";
409
- changes.push(
410
- `CREATE ${unique}INDEX if not exists \`${indexName}\` ON \`${tableName}\` (${columns});`,
411
- );
614
+ changes.push({
615
+ change: `CREATE ${unique}INDEX if not exists \`${indexName}\` ON \`${tableName}\` (${columns});`,
616
+ });
412
617
  }
413
618
 
414
619
  // Create foreign keys for new table
415
620
  for (const [fkName, dbFK] of Object.entries(dbTable.foreignKeys)) {
416
- changes.push(
417
- `ALTER TABLE \`${tableName}\` ADD CONSTRAINT \`${fkName}\` FOREIGN KEY (\`${dbFK.column}\`) REFERENCES \`${dbFK.referencedTable}\` (\`${dbFK.referencedColumn}\`);`,
418
- );
621
+ changes.push({
622
+ change: `ALTER TABLE \`${tableName}\` ADD CONSTRAINT \`${fkName}\` FOREIGN KEY (\`${dbFK.column}\`) REFERENCES \`${dbFK.referencedTable}\` (\`${dbFK.referencedColumn}\`);`,
623
+ });
419
624
  }
420
625
  continue;
421
626
  }
@@ -428,20 +633,97 @@ function generateSchemaChanges(
428
633
  // Column exists in database but not in schema - create it
429
634
  const type = dbCol.COLUMN_TYPE;
430
635
  const nullable = dbCol.IS_NULLABLE === "YES" ? "NULL" : "NOT NULL";
431
- changes.push(`ALTER TABLE \`${tableName}\` ADD COLUMN IF NOT EXISTS \`${colName}\` ${type} ${nullable};`);
636
+ let premigrationId = nullable === "NOT NULL" ? uuid() : undefined;
637
+ const defaultValue = dbCol.COLUMN_DEFAULT;
638
+ if (nullable === "NOT NULL") {
639
+ premigrationId = uuid();
640
+ preMigrations[premigrationId] = {
641
+ tableName,
642
+ dbTable,
643
+ colName,
644
+ type,
645
+ migrationType: "NEW_FIELD_NOT_NULL",
646
+ defaultValue,
647
+ };
648
+ }
649
+ changes.push({
650
+ change: `ALTER TABLE \`${tableName}\` ADD COLUMN IF NOT EXISTS \`${colName}\` ${type} ${nullable} ${
651
+ defaultValue === undefined || defaultValue === null
652
+ ? ""
653
+ : `DEFAULT ${buildDefault({
654
+ tableName,
655
+ dbTable,
656
+ colName,
657
+ type,
658
+ migrationType: "INLINE",
659
+ defaultValue: defaultValue,
660
+ })}`
661
+ };`,
662
+ premigrationId,
663
+ });
432
664
  continue;
433
665
  }
434
666
 
435
- // Check for type changes
667
+ // Check for column changes (type, nullability, or default value)
436
668
  const normalizedDbType = normalizeMySQLType(dbCol.COLUMN_TYPE);
437
669
  const normalizedDrizzleType = normalizeMySQLType(drizzleCol.getSQLType());
670
+ const nullable = dbCol.IS_NULLABLE === "YES" ? "NULL" : "NOT NULL";
671
+ const dbIsNotNull = nullable === "NOT NULL";
672
+ const drizzleIsNotNull = drizzleCol.notNull;
673
+
674
+ // Check if type has changed
675
+ const typeChanged = normalizedDbType !== normalizedDrizzleType;
676
+
677
+ // Check if nullability has changed
678
+ const nullabilityChanged = dbIsNotNull !== drizzleIsNotNull;
438
679
 
439
- if (normalizedDbType !== normalizedDrizzleType) {
680
+ // Check if default value has changed
681
+ const hasDrizzleDefault = drizzleCol.default !== null && drizzleCol.default !== undefined;
682
+ const hasDbDefault = dbCol.COLUMN_DEFAULT !== null && dbCol.COLUMN_DEFAULT !== undefined;
683
+ const defaultChanged =
684
+ hasDrizzleDefault && hasDbDefault && drizzleCol.default !== dbCol.COLUMN_DEFAULT;
685
+
686
+ // Column needs modification if any of these changed
687
+ if (typeChanged || nullabilityChanged || defaultChanged) {
440
688
  const type = dbCol.COLUMN_TYPE; // Use database type as source of truth
441
- const nullable = dbCol.IS_NULLABLE === "YES" ? "NULL" : "NOT NULL";
442
- changes.push(
443
- `ALTER TABLE \`${tableName}\` MODIFY COLUMN \`${colName}\` IF EXISTS ${type} ${nullable};`,
444
- );
689
+ const defaultValue = dbCol.COLUMN_DEFAULT;
690
+
691
+ // Determine if we need a pre-migration for NOT NULL constraint
692
+ let premigrationId: string | undefined = undefined;
693
+ if (dbIsNotNull && !drizzleIsNotNull) {
694
+ // Changing from NULL to NOT NULL - need pre-migration
695
+ premigrationId = uuid();
696
+ preMigrations[premigrationId] = {
697
+ tableName,
698
+ dbTable,
699
+ colName,
700
+ type,
701
+ migrationType: "MODIFY_NOT_NULL",
702
+ defaultValue: defaultValue,
703
+ };
704
+ }
705
+
706
+ // Build DEFAULT clause if default value exists
707
+ let defaultClause = "";
708
+ if (defaultValue !== undefined && defaultValue !== null) {
709
+ const defaultValueObj: PreMigrationNotNull = {
710
+ tableName,
711
+ dbTable,
712
+ colName,
713
+ type,
714
+ migrationType: "INLINE",
715
+ defaultValue: defaultValue,
716
+ };
717
+ defaultClause = ` DEFAULT ${buildDefault(defaultValueObj)}`;
718
+ }
719
+
720
+ // Generate MODIFY COLUMN statement
721
+ const modifyStatement = `ALTER TABLE \`${tableName}\` MODIFY COLUMN IF EXISTS \`${colName}\` ${type} ${nullable}${defaultClause};`;
722
+
723
+ changes.push({
724
+ change: modifyStatement,
725
+ premigrationId,
726
+ });
445
727
  }
446
728
  }
447
729
 
@@ -482,9 +764,9 @@ function generateSchemaChanges(
482
764
  // Index exists in database but not in schema - create it
483
765
  const columns = dbIndex.columns.map((col) => `\`${col}\``).join(", ");
484
766
  const unique = dbIndex.unique ? "UNIQUE " : "";
485
- changes.push(
486
- `CREATE ${unique}INDEX if not exists \`${indexName}\` ON \`${tableName}\` (${columns});`,
487
- );
767
+ changes.push({
768
+ change: `CREATE ${unique}INDEX if not exists \`${indexName}\` ON \`${tableName}\` (${columns});`,
769
+ });
488
770
  continue;
489
771
  }
490
772
 
@@ -496,12 +778,12 @@ function generateSchemaChanges(
496
778
  dbIndex.unique !== drizzleIndex instanceof UniqueConstraintBuilder
497
779
  ) {
498
780
  // Drop and recreate index using database values
499
- changes.push(`DROP INDEX \`${indexName}\` ON \`${tableName}\`;`);
781
+ changes.push({ change: `DROP INDEX \`${indexName}\` ON \`${tableName}\`;` });
500
782
  const columns = dbIndex.columns.map((col) => `\`${col}\``).join(", ");
501
783
  const unique = dbIndex.unique ? "UNIQUE " : "";
502
- changes.push(
503
- `CREATE ${unique}INDEX if not exists \`${indexName}\` ON \`${tableName}\` (${columns});`,
504
- );
784
+ changes.push({
785
+ change: `CREATE ${unique}INDEX if not exists \`${indexName}\` ON \`${tableName}\` (${columns});`,
786
+ });
505
787
  }
506
788
  }
507
789
 
@@ -516,9 +798,9 @@ function generateSchemaChanges(
516
798
 
517
799
  if (!drizzleFK) {
518
800
  // Foreign key exists in database but not in schema - drop it
519
- changes.push(
520
- `ALTER TABLE \`${tableName}\` ADD CONSTRAINT \`${fkName}\` FOREIGN KEY (\`${dbFK.column}\`) REFERENCES \`${dbFK.referencedTable}\` (\`${dbFK.referencedColumn}\`);`,
521
- );
801
+ changes.push({
802
+ change: `ALTER TABLE \`${tableName}\` ADD CONSTRAINT \`${fkName}\` FOREIGN KEY (\`${dbFK.column}\`) REFERENCES \`${dbFK.referencedTable}\` (\`${dbFK.referencedColumn}\`);`,
803
+ });
522
804
  continue;
523
805
  }
524
806
  }
@@ -539,7 +821,9 @@ function generateSchemaChanges(
539
821
  if (drizzleForeignKey) {
540
822
  const fkName = getForeignKeyName(drizzleForeignKey);
541
823
  if (fkName) {
542
- changes.push(`ALTER TABLE \`${tableName}\` DROP FOREIGN KEY \`${fkName}\`;`);
824
+ changes.push({
825
+ change: `ALTER TABLE \`${tableName}\` DROP FOREIGN KEY \`${fkName}\`;`,
826
+ });
543
827
  } else {
544
828
  // @ts-ignore
545
829
  const columns = drizzleForeignKey.columns;
@@ -556,7 +840,7 @@ function generateSchemaChanges(
556
840
  }
557
841
  }
558
842
 
559
- return changes;
843
+ return { changes, preMigrations };
560
844
  }
561
845
 
562
846
  /**
@@ -618,6 +902,7 @@ export const updateMigration = async (options: any) => {
618
902
  autoincrement: (column as any).autoincrement,
619
903
  columnType: column.columnType,
620
904
  name: column.name,
905
+ default: metadata.columns.email.hasDefault ? String(column.default) : undefined,
621
906
  getSQLType: () => column.getSQLType(),
622
907
  };
623
908
  });
@@ -638,7 +923,7 @@ export const updateMigration = async (options: any) => {
638
923
  options.output,
639
924
  );
640
925
 
641
- if (createStatements.length) {
926
+ if (createStatements.changes.length) {
642
927
  // Generate migration file content
643
928
  const migrationFile = generateMigrationFile(createStatements, version);
644
929