masterrecord 0.3.46 → 0.3.48

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.
@@ -39,10 +39,10 @@ module.exports = ${this.name};
39
39
 
40
40
  alterColumn(type, name, parent){
41
41
  if(type === "up"){
42
- this.#up += os.EOL + ` this.alterColumn(table.${name});`
42
+ this.#up += os.EOL + ` await this.alterColumn(table.${name});`
43
43
  }
44
44
  else{
45
- this.#down += os.EOL + ` this.alterColumn(table.${name});`
45
+ this.#down += os.EOL + ` await this.alterColumn(table.${name});`
46
46
  }
47
47
  }
48
48
  createTable(type, name){
@@ -56,29 +56,29 @@ module.exports = ${this.name};
56
56
 
57
57
  addColumn(type, name, parent){
58
58
  if(type === "up"){
59
- this.#up += os.EOL + ` this.addColumn(table.${name});`
59
+ this.#up += os.EOL + ` await this.addColumn(table.${name});`
60
60
  }
61
61
  else{
62
- this.#down += os.EOL + ` this.addColumn(table.${name});`
62
+ this.#down += os.EOL + ` await this.addColumn(table.${name});`
63
63
  }
64
64
  }
65
65
  //this.addColumn(table.${parent}.${name});`
66
66
 
67
67
  dropTable(type, name){
68
68
  if(type === "up"){
69
- this.#down += os.EOL + ` this.dropTable(table.${name});`
69
+ this.#down += os.EOL + ` await this.dropTable(table.${name});`
70
70
  }
71
71
  else{
72
- this.#down += os.EOL + ` this.dropTable(table.${name});`
72
+ this.#down += os.EOL + ` await this.dropTable(table.${name});`
73
73
  }
74
74
  }
75
75
 
76
76
  dropColumn(type, name, parent){
77
77
  if(type === "up"){
78
- this.#up += os.EOL + ` this.dropColumn(table.${name});`
78
+ this.#up += os.EOL + ` await this.dropColumn(table.${name});`
79
79
  }
80
80
  else{
81
- this.#down += os.EOL + ` this.dropColumn(table.${name});`
81
+ this.#down += os.EOL + ` await this.dropColumn(table.${name});`
82
82
  }
83
83
  }
84
84
 
@@ -187,7 +187,7 @@ module.exports = ${this.name};
187
187
 
188
188
  this.#up += os.EOL + ` ];`;
189
189
  this.#up += os.EOL + ` for (const record of factoryRecords) {`;
190
- this.#up += os.EOL + ` this.seed('${tableName}', record);`;
190
+ this.#up += os.EOL + ` await this.seed('${tableName}', record);`;
191
191
  this.#up += os.EOL + ` }`;
192
192
  } else {
193
193
  // Standard individual inserts for non-factory or small batches
@@ -214,10 +214,10 @@ module.exports = ${this.name};
214
214
  const formattedRecord = JSON.stringify(cleanRecord, null, 12)
215
215
  .split('\n')
216
216
  .join(os.EOL + ' ');
217
- this.#up += os.EOL + ` this.seed('${tableName}', ${formattedRecord});`;
217
+ this.#up += os.EOL + ` await this.seed('${tableName}', ${formattedRecord});`;
218
218
  } else {
219
219
  // Single-line format
220
- this.#up += os.EOL + ` this.seed('${tableName}', ${recordStr});`;
220
+ this.#up += os.EOL + ` await this.seed('${tableName}', ${recordStr});`;
221
221
  }
222
222
  }
223
223
  });
@@ -257,7 +257,7 @@ module.exports = ${this.name};
257
257
 
258
258
  this.#up += os.EOL + ` await existing.save();`;
259
259
  this.#up += os.EOL + ` } else {`;
260
- this.#up += os.EOL + ` this.seed('${tableName}', ${JSON.stringify(cleanRecord)});`;
260
+ this.#up += os.EOL + ` await this.seed('${tableName}', ${JSON.stringify(cleanRecord)});`;
261
261
  this.#up += os.EOL + ` }`;
262
262
  this.#up += os.EOL + ` }`;
263
263
  }
@@ -158,7 +158,7 @@ class schema{
158
158
  }
159
159
 
160
160
  // create obj to convert into create sql
161
- addColumn(table){
161
+ async addColumn(table){
162
162
  // todo need to work on add column for mysql
163
163
  if(table){
164
164
  if(this.context.isSQLite){
@@ -168,7 +168,7 @@ class schema{
168
168
  // This allows explicit column definitions to work, not just CLI-generated migrations
169
169
  // Note: No need to set table.realDataType - columnMapping handles type conversion internally
170
170
  var query = queryBuilder.addColum(table);
171
- this.context._execute(query);
171
+ await this.context._execute(query);
172
172
  }
173
173
 
174
174
  if(this.context.isMySQL){
@@ -176,7 +176,7 @@ class schema{
176
176
  var queryBuilder = new sqlquery();
177
177
  // Note: No need to set table.realDataType - columnMapping handles type conversion internally
178
178
  var query = queryBuilder.addColum(table);
179
- this.context._execute(query);
179
+ await this.context._execute(query);
180
180
  }
181
181
 
182
182
  if(this.context.isPostgres){
@@ -184,14 +184,14 @@ class schema{
184
184
  var queryBuilder = new postgresQuery();
185
185
  // Note: No need to set table.realDataType - columnMapping handles type conversion internally
186
186
  var query = queryBuilder.addColum(table);
187
- this.context._execute(query);
187
+ await this.context._execute(query);
188
188
  }
189
189
  }
190
190
 
191
191
  // add column to database
192
192
  }
193
193
 
194
- dropColumn(table){
194
+ async dropColumn(table){
195
195
  if(table){
196
196
  if(this.fullTable){
197
197
  // drop column
@@ -199,21 +199,21 @@ class schema{
199
199
  var sqliteQuery = require("./migrationSQLiteQuery");
200
200
  var queryBuilder = new sqliteQuery();
201
201
  var query = queryBuilder.dropColumn(table);
202
- this.context._execute(query);
202
+ await this.context._execute(query);
203
203
  }
204
204
 
205
205
  if(this.context.isMySQL){
206
206
  var sqlquery = require("./migrationMySQLQuery");
207
207
  var queryBuilder = new sqlquery();
208
208
  var query = queryBuilder.dropColumn(table);
209
- this.context._execute(query);
209
+ await this.context._execute(query);
210
210
  }
211
211
 
212
212
  if(this.context.isPostgres){
213
213
  var postgresQuery = require("./migrationPostgresQuery");
214
214
  var queryBuilder = new postgresQuery();
215
215
  var query = queryBuilder.dropColumn(table);
216
- this.context._execute(query);
216
+ await this.context._execute(query);
217
217
  }
218
218
 
219
219
  }else{
@@ -237,50 +237,49 @@ class schema{
237
237
  var sqliteQuery = require("./migrationSQLiteQuery");
238
238
  var queryBuilder = new sqliteQuery();
239
239
  var query = queryBuilder.createTable(table);
240
- this.context._execute(query);
240
+ await this.context._execute(query);
241
241
  }
242
242
 
243
243
  if(this.context.isMySQL){
244
244
  var sqlquery = require("./migrationMySQLQuery");
245
245
  var queryBuilder = new sqlquery();
246
246
  var query = queryBuilder.createTable(table);
247
- this.context._execute(query);
247
+ await this.context._execute(query);
248
248
  }
249
249
 
250
250
  if(this.context.isPostgres){
251
251
  var postgresQuery = require("./migrationPostgresQuery");
252
252
  var queryBuilder = new postgresQuery();
253
253
  var query = queryBuilder.createTable(table);
254
- this.context._execute(query);
254
+ await this.context._execute(query);
255
255
  }
256
256
 
257
257
  // Create indexes for columns that have .index() defined
258
- const self = this;
259
- Object.keys(table).forEach(function(key){
258
+ for(const key of Object.keys(table)){
260
259
  if(typeof table[key] === "object" && table[key].indexes && !key.startsWith('__')){
261
260
  const columnName = table[key].name;
262
- table[key].indexes.forEach(function(indexName){
261
+ for(const indexName of table[key].indexes){
263
262
  const indexInfo = {
264
263
  tableName: tableName,
265
264
  columnName: columnName,
266
265
  indexName: indexName
267
266
  };
268
- self.createIndex(indexInfo);
269
- });
267
+ await this.createIndex(indexInfo);
268
+ }
270
269
  }
271
- });
270
+ }
272
271
 
273
272
  // Create composite indexes
274
273
  if (table.__compositeIndexes) {
275
- table.__compositeIndexes.forEach(function(compositeIdx) {
274
+ for(const compositeIdx of table.__compositeIndexes){
276
275
  const indexInfo = {
277
276
  tableName: tableName,
278
277
  columns: compositeIdx.columns,
279
278
  indexName: compositeIdx.name,
280
279
  unique: compositeIdx.unique
281
280
  };
282
- self.createCompositeIndex(indexInfo);
283
- });
281
+ await this.createCompositeIndex(indexInfo);
282
+ }
284
283
  }
285
284
  }
286
285
  }else{
@@ -297,8 +296,12 @@ class schema{
297
296
  const existingNames = new Set((existing || []).map(c => (c.name || c.COLUMN_NAME))); // both engines map to name
298
297
  // Add missing columns only (safe path)
299
298
  for (var key in table) {
300
- if(typeof table[key] === 'object'){
299
+ // Skip metadata properties (indexes, __compositeIndexes, __name, etc.)
300
+ if(key === 'indexes' || key.startsWith('__')) continue;
301
+ if(typeof table[key] === 'object' && !Array.isArray(table[key])){
301
302
  const col = table[key];
303
+ // Skip if missing name/type (not a valid column definition)
304
+ if(!col.name || !col.type) continue;
302
305
  // Skip relationships
303
306
  if(col.type === 'hasOne' || col.type === 'hasMany' || col.type === 'hasManyThrough') continue;
304
307
  const colName = (col.relationshipType === 'belongsTo' && col.foreignKey) ? col.foreignKey : col.name;
@@ -315,21 +318,21 @@ class schema{
315
318
  var queryBuilder = new sqliteQuery();
316
319
  // Build a conservative column add (no NOT NULL without default)
317
320
  const add = queryBuilder.addColum({ tableName, name: colName });
318
- this.context._execute(add);
321
+ await this.context._execute(add);
319
322
  }
320
323
  if(this.context.isMySQL){
321
324
  var sqlquery = require("./migrationMySQLQuery");
322
325
  var queryBuilder = new sqlquery();
323
326
  newCol.realDataType = queryBuilder.typeManager(col.type);
324
327
  const query = queryBuilder.addColum(newCol);
325
- this.context._execute(query);
328
+ await this.context._execute(query);
326
329
  }
327
330
  if(this.context.isPostgres){
328
331
  var postgresQuery = require("./migrationPostgresQuery");
329
332
  var queryBuilder = new postgresQuery();
330
333
  newCol.realDataType = queryBuilder.typeManager(col.type);
331
334
  const query = queryBuilder.addColum(newCol);
332
- this.context._execute(query);
335
+ await this.context._execute(query);
333
336
  }
334
337
  }
335
338
  }
@@ -337,8 +340,10 @@ class schema{
337
340
  // Detect modifications (nullable/default/type)
338
341
  const desiredCols = [];
339
342
  for (var key in table) {
340
- if(typeof table[key] === 'object'){
343
+ if(key === 'indexes' || key.startsWith('__')) continue;
344
+ if(typeof table[key] === 'object' && !Array.isArray(table[key])){
341
345
  const col = table[key];
346
+ if(!col.name || !col.type) continue;
342
347
  if(col.type === 'hasOne' || col.type === 'hasMany' || col.type === 'hasManyThrough') continue;
343
348
  const colName = (col.relationshipType === 'belongsTo' && col.foreignKey) ? col.foreignKey : col.name;
344
349
  desiredCols.push({ name: colName, col });
@@ -411,7 +416,7 @@ class schema{
411
416
  defPart = ' DEFAULT NULL';
412
417
  }
413
418
  const alter = `ALTER TABLE ${tableName} MODIFY COLUMN ${d.name} ${type} ${nullPart}${defPart}`;
414
- this.context._execute(alter);
419
+ await this.context._execute(alter);
415
420
  }
416
421
  }
417
422
  }
@@ -421,10 +426,10 @@ class schema{
421
426
  var queryBuilder = new sqliteQuery();
422
427
  // rename old table
423
428
  const rename = queryBuilder.renameTable({ tableName, newName: "_temp_alter_column_update" });
424
- this.context._execute(rename);
429
+ await this.context._execute(rename);
425
430
  // create new with desired schema
426
431
  const create = queryBuilder.createTable(table);
427
- this.context._execute(create);
432
+ await this.context._execute(create);
428
433
  // compute common columns
429
434
  const oldInfo = await engine.getTableInfo(tableName.replace(/.*/, '_temp_alter_column_update')) || await engine.getTableInfo("_temp_alter_column_update");
430
435
  const oldNames = new Set((oldInfo || existing).map(r => r.name));
@@ -433,35 +438,35 @@ class schema{
433
438
  if(common.length > 0){
434
439
  const cols = common.join(',');
435
440
  const insert = `INSERT INTO ${tableName} (${cols}) SELECT ${cols} FROM _temp_alter_column_update`;
436
- this.context._execute(insert);
441
+ await this.context._execute(insert);
437
442
  }
438
443
  const drop = queryBuilder.dropTable("_temp_alter_column_update");
439
- this.context._execute(drop);
444
+ await this.context._execute(drop);
440
445
  }
441
446
  }
442
447
 
443
448
 
444
- dropTable(table){
449
+ async dropTable(table){
445
450
  if(table){
446
451
  if(this.context.isSQLite){
447
452
  var sqliteQuery = require("./migrationSQLiteQuery");
448
453
  var queryBuilder = new sqliteQuery();
449
454
  var query = queryBuilder.dropTable(table.__name);
450
- this.context._execute(query);
455
+ await this.context._execute(query);
451
456
  }
452
457
 
453
458
  if(this.context.isMySQL){
454
459
  var sqlquery = require("./migrationMySQLQuery");
455
460
  var queryBuilder = new sqlquery();
456
461
  var query = queryBuilder.dropTable(table.__name);
457
- this.context._execute(query);
462
+ await this.context._execute(query);
458
463
  }
459
464
 
460
465
  if(this.context.isPostgres){
461
466
  var postgresQuery = require("./migrationPostgresQuery");
462
467
  var queryBuilder = new postgresQuery();
463
468
  var query = queryBuilder.dropTable(table.__name);
464
- this.context._execute(query);
469
+ await this.context._execute(query);
465
470
  }
466
471
  }
467
472
  }
@@ -479,7 +484,7 @@ class schema{
479
484
 
480
485
 
481
486
  //"dbo.People", "Location"
482
- alterColumn(table){
487
+ async alterColumn(table){
483
488
  if(table){
484
489
  if(this.fullTable){
485
490
  if(this.context.isSQLite){
@@ -488,7 +493,7 @@ class schema{
488
493
  var queryObj = queryBuilder.alterColumn(this.fullTable.new, table);
489
494
  for (var key in queryObj) {
490
495
  var query = queryObj[key];
491
- this.context._execute(query);
496
+ await this.context._execute(query);
492
497
  }
493
498
  }
494
499
 
@@ -496,14 +501,14 @@ class schema{
496
501
  var sqlquery = require("./migrationMySQLQuery");
497
502
  var queryBuilder = new sqlquery();
498
503
  var query = queryBuilder.alterColumn(table);
499
- this.context._execute(query);
504
+ await this.context._execute(query);
500
505
  }
501
506
 
502
507
  if(this.context.isPostgres){
503
508
  var postgresQuery = require("./migrationPostgresQuery");
504
509
  var queryBuilder = new postgresQuery();
505
510
  var query = queryBuilder.alterColumn(table);
506
- this.context._execute(query);
511
+ await this.context._execute(query);
507
512
  }
508
513
 
509
514
  }else{
@@ -512,132 +517,132 @@ class schema{
512
517
  }
513
518
  }
514
519
 
515
- renameColumn(table){
520
+ async renameColumn(table){
516
521
  if(table){
517
522
  if(this.context.isSQLite){
518
523
  var sqliteQuery = require("./migrationSQLiteQuery");
519
524
  var queryBuilder = new sqliteQuery();
520
525
  var query = queryBuilder.renameColumn(table);
521
- this.context._execute(query);
526
+ await this.context._execute(query);
522
527
  }
523
528
 
524
529
  if(this.context.isMySQL){
525
530
  var sqlquery = require("./migrationMySQLQuery");
526
531
  var queryBuilder = new sqlquery();
527
532
  var query = queryBuilder.renameColumn(table);
528
- this.context._execute(query);
533
+ await this.context._execute(query);
529
534
  }
530
535
 
531
536
  if(this.context.isPostgres){
532
537
  var postgresQuery = require("./migrationPostgresQuery");
533
538
  var queryBuilder = new postgresQuery();
534
539
  var query = queryBuilder.renameColumn(table);
535
- this.context._execute(query);
540
+ await this.context._execute(query);
536
541
  }
537
542
  }
538
543
  }
539
544
 
540
- createIndex(indexInfo){
545
+ async createIndex(indexInfo){
541
546
  if(indexInfo){
542
547
  if(this.context.isSQLite){
543
548
  var sqliteQuery = require("./migrationSQLiteQuery");
544
549
  var queryBuilder = new sqliteQuery();
545
550
  var query = queryBuilder.createIndex(indexInfo);
546
- this.context._execute(query);
551
+ await this.context._execute(query);
547
552
  }
548
553
 
549
554
  if(this.context.isMySQL){
550
555
  var sqlquery = require("./migrationMySQLQuery");
551
556
  var queryBuilder = new sqlquery();
552
557
  var query = queryBuilder.createIndex(indexInfo);
553
- this.context._execute(query);
558
+ await this.context._execute(query);
554
559
  }
555
560
 
556
561
  if(this.context.isPostgres){
557
562
  var postgresQuery = require("./migrationPostgresQuery");
558
563
  var queryBuilder = new postgresQuery();
559
564
  var query = queryBuilder.createIndex(indexInfo);
560
- this.context._execute(query);
565
+ await this.context._execute(query);
561
566
  }
562
567
  }
563
568
  }
564
569
 
565
- dropIndex(indexInfo){
570
+ async dropIndex(indexInfo){
566
571
  if(indexInfo){
567
572
  if(this.context.isSQLite){
568
573
  var sqliteQuery = require("./migrationSQLiteQuery");
569
574
  var queryBuilder = new sqliteQuery();
570
575
  var query = queryBuilder.dropIndex(indexInfo);
571
- this.context._execute(query);
576
+ await this.context._execute(query);
572
577
  }
573
578
 
574
579
  if(this.context.isMySQL){
575
580
  var sqlquery = require("./migrationMySQLQuery");
576
581
  var queryBuilder = new sqlquery();
577
582
  var query = queryBuilder.dropIndex(indexInfo);
578
- this.context._execute(query);
583
+ await this.context._execute(query);
579
584
  }
580
585
 
581
586
  if(this.context.isPostgres){
582
587
  var postgresQuery = require("./migrationPostgresQuery");
583
588
  var queryBuilder = new postgresQuery();
584
589
  var query = queryBuilder.dropIndex(indexInfo);
585
- this.context._execute(query);
590
+ await this.context._execute(query);
586
591
  }
587
592
  }
588
593
  }
589
594
 
590
- createCompositeIndex(indexInfo){
595
+ async createCompositeIndex(indexInfo){
591
596
  if(indexInfo){
592
597
  if(this.context.isSQLite){
593
598
  var sqliteQuery = require("./migrationSQLiteQuery");
594
599
  var queryBuilder = new sqliteQuery();
595
600
  var query = queryBuilder.createCompositeIndex(indexInfo);
596
- this.context._execute(query);
601
+ await this.context._execute(query);
597
602
  }
598
603
 
599
604
  if(this.context.isMySQL){
600
605
  var sqlquery = require("./migrationMySQLQuery");
601
606
  var queryBuilder = new sqlquery();
602
607
  var query = queryBuilder.createCompositeIndex(indexInfo);
603
- this.context._execute(query);
608
+ await this.context._execute(query);
604
609
  }
605
610
 
606
611
  if(this.context.isPostgres){
607
612
  var postgresQuery = require("./migrationPostgresQuery");
608
613
  var queryBuilder = new postgresQuery();
609
614
  var query = queryBuilder.createCompositeIndex(indexInfo);
610
- this.context._execute(query);
615
+ await this.context._execute(query);
611
616
  }
612
617
  }
613
618
  }
614
619
 
615
- dropCompositeIndex(indexInfo){
620
+ async dropCompositeIndex(indexInfo){
616
621
  if(indexInfo){
617
622
  if(this.context.isSQLite){
618
623
  var sqliteQuery = require("./migrationSQLiteQuery");
619
624
  var queryBuilder = new sqliteQuery();
620
625
  var query = queryBuilder.dropCompositeIndex(indexInfo);
621
- this.context._execute(query);
626
+ await this.context._execute(query);
622
627
  }
623
628
 
624
629
  if(this.context.isMySQL){
625
630
  var sqlquery = require("./migrationMySQLQuery");
626
631
  var queryBuilder = new sqlquery();
627
632
  var query = queryBuilder.dropCompositeIndex(indexInfo);
628
- this.context._execute(query);
633
+ await this.context._execute(query);
629
634
  }
630
635
 
631
636
  if(this.context.isPostgres){
632
637
  var postgresQuery = require("./migrationPostgresQuery");
633
638
  var queryBuilder = new postgresQuery();
634
639
  var query = queryBuilder.dropCompositeIndex(indexInfo);
635
- this.context._execute(query);
640
+ await this.context._execute(query);
636
641
  }
637
642
  }
638
643
  }
639
644
 
640
- seed(tableName, rows){
645
+ async seed(tableName, rows){
641
646
  if(!tableName || !rows){ return; }
642
647
  const items = Array.isArray(rows) ? rows : [rows];
643
648
 
@@ -649,7 +654,7 @@ class schema{
649
654
  // SQLite: Use INSERT OR IGNORE for idempotency
650
655
  const query = queryBuilder.insertSeedData(tableName, row);
651
656
  const idempotentQuery = query.replace(/^INSERT INTO/, 'INSERT OR IGNORE INTO');
652
- this.context._execute(idempotentQuery);
657
+ await this.context._execute(idempotentQuery);
653
658
  }
654
659
  }
655
660
 
@@ -660,7 +665,7 @@ class schema{
660
665
  // MySQL: Use INSERT IGNORE for idempotency
661
666
  const query = queryBuilder.insertSeedData(tableName, row);
662
667
  const idempotentQuery = query.replace(/^INSERT INTO/, 'INSERT IGNORE INTO');
663
- this.context._execute(idempotentQuery);
668
+ await this.context._execute(idempotentQuery);
664
669
  }
665
670
  }
666
671
 
@@ -672,7 +677,7 @@ class schema{
672
677
  // Note: This requires a unique constraint or primary key
673
678
  const query = queryBuilder.insertSeedData(tableName, row);
674
679
  const idempotentQuery = query + ' ON CONFLICT DO NOTHING';
675
- this.context._execute(idempotentQuery);
680
+ await this.context._execute(idempotentQuery);
676
681
  }
677
682
  }
678
683
  }
@@ -682,7 +687,7 @@ class schema{
682
687
  * @param {string} tableName - Name of the table
683
688
  * @param {Array} rows - Array of data objects
684
689
  */
685
- bulkSeed(tableName, rows){
690
+ async bulkSeed(tableName, rows){
686
691
  if(!tableName || !rows || rows.length === 0){ return; }
687
692
 
688
693
  if(this.context.isSQLite){
@@ -691,7 +696,7 @@ class schema{
691
696
  const query = queryBuilder.bulkInsertSeedData(tableName, rows);
692
697
  if(query){
693
698
  const idempotentQuery = query.replace(/^INSERT INTO/, 'INSERT OR IGNORE INTO');
694
- this.context._execute(idempotentQuery);
699
+ await this.context._execute(idempotentQuery);
695
700
  }
696
701
  }
697
702
 
@@ -701,7 +706,7 @@ class schema{
701
706
  const query = queryBuilder.bulkInsertSeedData(tableName, rows);
702
707
  if(query){
703
708
  const idempotentQuery = query.replace(/^INSERT INTO/, 'INSERT IGNORE INTO');
704
- this.context._execute(idempotentQuery);
709
+ await this.context._execute(idempotentQuery);
705
710
  }
706
711
  }
707
712
 
@@ -711,7 +716,7 @@ class schema{
711
716
  const query = queryBuilder.bulkInsertSeedData(tableName, rows);
712
717
  if(query){
713
718
  const idempotentQuery = query + ' ON CONFLICT DO NOTHING';
714
- this.context._execute(idempotentQuery);
719
+ await this.context._execute(idempotentQuery);
715
720
  }
716
721
  }
717
722
  }
package/context.js CHANGED
@@ -1714,7 +1714,7 @@ class context {
1714
1714
  * context._execute('CREATE INDEX idx_user_email ON User(email)');
1715
1715
  */
1716
1716
  _execute(query) {
1717
- this._SQLEngine._execute(query);
1717
+ return this._SQLEngine._execute(query);
1718
1718
  }
1719
1719
 
1720
1720
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "masterrecord",
3
- "version": "0.3.46",
3
+ "version": "0.3.48",
4
4
  "description": "An Object-relational mapping for the Master framework. Master Record connects classes to relational database tables to establish a database with almost zero-configuration ",
5
5
  "main": "MasterRecord.js",
6
6
  "bin": {
package/readme.md CHANGED
@@ -3369,6 +3369,27 @@ user.name = null; // Error if name is { nullable: false }
3369
3369
 
3370
3370
  ## Changelog
3371
3371
 
3372
+ ### Version 0.3.48 (2026-02-20) - FIX: Complete Async Migration Pipeline for MySQL/PostgreSQL
3373
+
3374
+ #### Bug Fixed: Migration methods not properly awaiting async database operations
3375
+ - **FIXED**: All migration schema methods (`createTable`, `addColumn`, `dropColumn`, `dropTable`, `alterColumn`, `renameColumn`, `createIndex`, `dropIndex`, `createCompositeIndex`, `dropCompositeIndex`, `seed`, `bulkSeed`) are now fully `async` and properly `await` all database operations
3376
+ - **Root Cause**: SQLite's `_execute()` is synchronous, but MySQL/PostgreSQL return Promises. Migration methods were calling `this.context._execute()` without `await`, causing operations to run out of order (e.g., CREATE INDEX running before CREATE TABLE finished)
3377
+ - **Solution**: Made all schema methods async, added `await` to every `_execute()` call, converted `forEach` loops to `for...of` for proper async iteration
3378
+ - **FIXED**: `context._execute()` now properly returns the engine's Promise (`return this._SQLEngine._execute(query)`)
3379
+ - **FIXED**: Added `_execute()` method to MySQL and PostgreSQL engines (previously only existed on SQLite)
3380
+ - **FIXED**: `syncTable()` no longer crashes on metadata properties (`indexes`, `__compositeIndexes`) — now filters them out before column iteration
3381
+ - **FIXED**: Migration template now generates `await` for all method calls in migration files
3382
+ - **FIXED**: Unhandled promise rejection crash — MySQL/PostgreSQL `_initPromise` now has `.catch(() => {})` to prevent Node.js crash before `_ensureReady()` can handle errors
3383
+ - **FIXED**: Added `_ready` flag to prevent duplicate `_ensureReady()` execution
3384
+
3385
+ #### Files Modified
3386
+ 1. **`Migrations/schema.js`** - All methods async, all `_execute` calls awaited, forEach→for...of, syncTable metadata filtering, `_ready` flag
3387
+ 2. **`Migrations/migrationTemplate.js`** - All generated method calls now include `await`
3388
+ 3. **`mySQLEngine.js`** - Added `_execute()` method
3389
+ 4. **`postgresEngine.js`** - Added `_execute()` method
3390
+ 5. **`context.js`** - `_execute()` returns engine result, `.catch()` on `_initPromise`
3391
+ 6. **`package.json`** - Updated to v0.3.48
3392
+
3372
3393
  ### Version 0.3.44 (2026-02-20) - FIX: MySQL/PostgreSQL Auto-Create Database During Migrations
3373
3394
 
3374
3395
  #### Bug Fixed: `update-database` failing when database doesn't exist yet (MySQL & PostgreSQL)