masterrecord 0.3.41 → 0.3.43

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.
@@ -24,12 +24,12 @@ class ${this.name} extends masterrecord.schema {
24
24
  }
25
25
 
26
26
  async up(table){
27
- this.init(table);
27
+ await this.init(table);
28
28
  ${this.#up}
29
29
  }
30
30
 
31
31
  async down(table){
32
- this.init(table);
32
+ await this.init(table);
33
33
  ${this.#down}
34
34
  }
35
35
  }
@@ -6,14 +6,27 @@ class schema{
6
6
  this._dbEnsured = false;
7
7
  }
8
8
 
9
+ /**
10
+ * Wait for async database initialization (MySQL/PostgreSQL) to complete.
11
+ * The context constructor fires off an async pool init that may not have
12
+ * finished by the time migration methods run. This must be awaited before
13
+ * accessing this.context._SQLEngine or this.context.db.
14
+ */
15
+ async _ensureReady(){
16
+ if(this.context && this.context._initPromise){
17
+ await this.context._initPromise;
18
+ }
19
+ }
9
20
 
10
- init(table){
21
+ async init(table){
22
+ // Wait for async DB init (MySQL/PostgreSQL) before any operations
23
+ await this._ensureReady();
11
24
  if(table){
12
25
  this.fullTable = table.___table;
13
26
  }
14
27
  // Ensure backing database exists for MySQL before running any DDL
15
28
  if(this.context && this.context.isMySQL && this._dbEnsured !== true){
16
- try{ this.createDatabase(); }catch(_){ /* best-effort */ }
29
+ try{ await this.createDatabase(); }catch(_){ /* best-effort */ }
17
30
  }
18
31
  }
19
32
 
@@ -83,6 +96,9 @@ class schema{
83
96
  }
84
97
 
85
98
  async createTable(table){
99
+ // Ensure async DB init is complete (safety net for older migrations
100
+ // that call this.init(table) without await)
101
+ await this._ensureReady();
86
102
 
87
103
  if(table){
88
104
  // If table exists, run sync instead of blind create
@@ -327,7 +343,7 @@ class schema{
327
343
  async createDatabase(){
328
344
  try{
329
345
  if(!(this.context && this.context.isMySQL)){ return; }
330
- const MySQLAsyncClient = require('masterrecord/mySQLAsyncConnect');
346
+ const MySQLAsyncClient = require('masterrecord/mySQLConnect');
331
347
  const client = this.context.db; // main client (may not be connected yet)
332
348
  if(!client || !client.config || !client.config.database){ return; }
333
349
  const dbName = client.config.database;
package/context.js CHANGED
@@ -712,11 +712,13 @@ class context {
712
712
  this.isPostgres = false;
713
713
 
714
714
  // MySQL is async - caller must await env()
715
- return (async () => {
715
+ // Store promise so migration schema can await it
716
+ this._initPromise = (async () => {
716
717
  this.db = await this.__mysqlInit(options, 'mysql2');
717
718
  // Note: engine is already set in __mysqlInit
718
719
  return this;
719
720
  })();
721
+ return this._initPromise;
720
722
  }
721
723
 
722
724
  // PostgreSQL initialization (async)
@@ -726,11 +728,13 @@ class context {
726
728
  this.isSQLite = false;
727
729
 
728
730
  // PostgreSQL is async - caller must await env()
729
- return (async () => {
731
+ // Store promise so migration schema can await it
732
+ this._initPromise = (async () => {
730
733
  this.db = await this.__postgresInit(options, 'pg');
731
734
  // Note: engine is already set in __postgresInit
732
735
  return this;
733
736
  })();
737
+ return this._initPromise;
734
738
  }
735
739
 
736
740
  throw new ConfigurationError(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "masterrecord",
3
- "version": "0.3.41",
3
+ "version": "0.3.43",
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,19 +3369,25 @@ user.name = null; // Error if name is { nullable: false }
3369
3369
 
3370
3370
  ## Changelog
3371
3371
 
3372
- ### Version 0.3.41 (2026-02-20) - FIX: add-migration No Longer Creates Unnecessary Database Connections
3372
+ ### Version 0.3.42 (2026-02-20) - FIX: Migration System + add-migration Improvements
3373
3373
 
3374
- #### Bug Fixed: `add-migration` creating real database connections and files
3374
+ #### Bug Fixed: `update-database` failing for MySQL/PostgreSQL with "Cannot read properties of null"
3375
+ - **FIXED**: Running `masterrecord update-database` with MySQL or PostgreSQL would crash with `Cannot read properties of null (reading 'tableExists')`
3376
+ - **Root Cause**: The migration `schema.js` constructor creates a new context instance, but MySQL/PostgreSQL database initialization is async. The `_SQLEngine` property was still `null` when `createTable` tried to use it because the async pool init hadn't completed yet.
3377
+ - **Solution**: Store the async init promise as `_initPromise` on the context instance. Added `_ensureReady()` method to `schema.js` that awaits it. Called in both `init()` and `createTable()` (safety net for existing migrations).
3378
+ - **Also fixed**: Typo in `schema.js` — `require('masterrecord/mySQLAsyncConnect')` corrected to `require('masterrecord/mySQLConnect')`
3379
+ - **Also fixed**: `init()` now properly `await`s `createDatabase()` instead of fire-and-forget
3380
+
3381
+ #### Bug Fixed: `add-migration` creating unnecessary database connections
3375
3382
  - **FIXED**: Running `masterrecord add-migration` would open a real database connection (creating SQLite files on disk, or connecting to MySQL/PostgreSQL) even though it only needs entity schemas and seed data to generate migration files
3376
- - **Problem**: On production servers, `add-migration` created unwanted `.sqlite3` files and printed misleading "SQLite database closed" messages
3377
- - **Root Cause**: The context constructor calls `env()` which initializes a full database connection; `add-migration` only needs entity metadata
3378
- - **Solution**: Added schema-only mode (`MASTERRECORD_SCHEMA_ONLY` env var) that sets database type flags for correct entity registration but skips all database initialization (no file creation, no connections)
3379
- - **Impact**: `add-migration` is now faster, creates no side effects, and works safely on production servers
3383
+ - **Solution**: Added schema-only mode (`MASTERRECORD_SCHEMA_ONLY` env var) that sets database type flags but skips all DB initialization
3380
3384
 
3381
3385
  #### Files Modified
3382
- 1. **`Migrations/cli.js`** - Set `MASTERRECORD_SCHEMA_ONLY=1` before context construction, removed unnecessary `close()` calls
3383
- 2. **`context.js`** - Added schema-only mode check in `env()` that returns early after setting type flags
3384
- 3. **`package.json`** - Updated to v0.3.41
3386
+ 1. **`Migrations/schema.js`** - Added `_ensureReady()`, made `init()` async with proper awaits, fixed `mySQLConnect` require
3387
+ 2. **`Migrations/migrationTemplate.js`** - New migrations now `await this.init(table)`
3388
+ 3. **`Migrations/cli.js`** - Schema-only mode for `add-migration`
3389
+ 4. **`context.js`** - Store `_initPromise` for MySQL/PostgreSQL async init, schema-only mode in `env()`
3390
+ 5. **`package.json`** - Updated to v0.3.42
3385
3391
 
3386
3392
  ### Version 0.3.39 (2026-02-09) - CRITICAL BUG FIX: Foreign Key String Values
3387
3393