masterrecord 0.3.18 → 0.3.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/readme.md +111 -36
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "masterrecord",
3
- "version": "0.3.18",
3
+ "version": "0.3.19",
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
@@ -23,8 +23,8 @@
23
23
  | Database | Version | Features |
24
24
  |------------|--------------|---------------------------------------------------|
25
25
  | PostgreSQL | 9.6+ (12+) | JSONB, UUID, async/await, connection pooling |
26
- | MySQL | 5.7+ (8.0+) | JSON, transactions, AUTO_INCREMENT |
27
- | SQLite | 3.x | Embedded, zero-config, file-based |
26
+ | MySQL | 5.7+ (8.0+) | JSON, async/await, connection pooling, AUTO_INCREMENT |
27
+ | SQLite | 3.x | Embedded, zero-config, file-based, async API wrapper |
28
28
 
29
29
  ## Table of Contents
30
30
 
@@ -64,9 +64,9 @@ npm install masterrecord better-sqlite3 # SQLite
64
64
  ### Dependencies
65
65
 
66
66
  MasterRecord includes the following database drivers by default:
67
- - `pg@^8.17.2` - PostgreSQL
68
- - `sync-mysql2@^1.0.8` - MySQL
69
- - `better-sqlite3@^12.6.2` - SQLite
67
+ - `pg@^8.17.2` - PostgreSQL (async)
68
+ - `mysql2@^3.11.5` - MySQL (async with connection pooling)
69
+ - `better-sqlite3@^12.6.2` - SQLite (async API wrapper for consistency)
70
70
 
71
71
  ## Two Patterns: Entity Framework & Active Record
72
72
 
@@ -212,7 +212,7 @@ const db = new AppContext();
212
212
  await db.saveChanges(); // PostgreSQL is async
213
213
  ```
214
214
 
215
- ### MySQL (Synchronous)
215
+ ### MySQL (Async with Connection Pooling)
216
216
 
217
217
  ```javascript
218
218
  class AppContext extends context {
@@ -225,19 +225,20 @@ class AppContext extends context {
225
225
  port: 3306,
226
226
  database: 'myapp',
227
227
  user: 'root',
228
- password: 'password'
228
+ password: 'password',
229
+ connectionLimit: 10 // Connection pool size (optional)
229
230
  });
230
231
 
231
232
  this.dbset(User);
232
233
  }
233
234
  }
234
235
 
235
- // Usage is synchronous
236
+ // Usage requires await (async like PostgreSQL)
236
237
  const db = new AppContext();
237
- db.saveChanges(); // No await needed
238
+ await db.saveChanges(); // MySQL now uses async/await
238
239
  ```
239
240
 
240
- ### SQLite (Synchronous)
241
+ ### SQLite (Async API)
241
242
 
242
243
  ```javascript
243
244
  class AppContext extends context {
@@ -252,6 +253,10 @@ class AppContext extends context {
252
253
  this.dbset(User);
253
254
  }
254
255
  }
256
+
257
+ // Usage requires await for consistency across databases
258
+ const db = new AppContext();
259
+ await db.saveChanges(); // SQLite now has async API wrapper
255
260
  ```
256
261
 
257
262
  ### Environment Files
@@ -593,33 +598,48 @@ masterrecord update-database-all # Apply all pending migrations
593
598
 
594
599
  ```javascript
595
600
  // db/migrations/20250111_143052_CreateUser.js
596
- module.exports = {
597
- up: function(table, schema) {
598
- // Create table
599
- schema.createTable(table.User);
601
+ const masterrecord = require('masterrecord');
602
+
603
+ class CreateUser extends masterrecord.schema {
604
+ constructor(context) {
605
+ super(context);
606
+ }
607
+
608
+ // IMPORTANT: Migrations must be async
609
+ async up(table) {
610
+ this.init(table);
611
+
612
+ // Create table (requires await)
613
+ await this.createTable(table.User);
600
614
 
601
615
  // Seed initial data
602
- schema.seed('User', {
616
+ this.seed('User', {
603
617
  name: 'Admin',
604
618
  email: 'admin@example.com',
605
619
  role: 'admin'
606
620
  });
607
- },
621
+ }
622
+
623
+ async down(table) {
624
+ this.init(table);
608
625
 
609
- down: function(table, schema) {
610
626
  // Rollback
611
- schema.dropTable(table.User);
627
+ this.dropTable(table.User);
612
628
  }
613
- };
629
+ }
630
+
631
+ module.exports = CreateUser;
614
632
  ```
615
633
 
616
634
  ### Migration Operations
617
635
 
618
636
  ```javascript
619
- module.exports = {
620
- up: function(table, schema) {
621
- // Create table
622
- schema.createTable(table.User);
637
+ class MyMigration extends masterrecord.schema {
638
+ async up(table) {
639
+ this.init(table);
640
+
641
+ // Create table (requires await)
642
+ await this.createTable(table.User);
623
643
 
624
644
  // Add column
625
645
  schema.addColumn({
@@ -1189,9 +1209,8 @@ const users = db._SQLEngine.exec(
1189
1209
  context.dbset(EntityClass)
1190
1210
  context.dbset(EntityClass, 'custom_table_name')
1191
1211
 
1192
- // Save changes
1193
- await context.saveChanges() // PostgreSQL (async)
1194
- context.saveChanges() // MySQL/SQLite (sync)
1212
+ // Save changes (all databases now async)
1213
+ await context.saveChanges() // PostgreSQL, MySQL, SQLite (all async)
1195
1214
 
1196
1215
  // Add/Remove entities
1197
1216
  context.EntityName.add(entity)
@@ -1585,9 +1604,9 @@ user.name = null; // Error if name is { nullable: false }
1585
1604
  | PostgreSQL | 9.6+ (12+) | Tested with 12, 13, 14, 15, 16 |
1586
1605
  | MySQL | 5.7+ (8.0+) | Tested with 8.0+ |
1587
1606
  | SQLite | 3.x | Any recent version |
1588
- | pg | 8.17.2+ | PostgreSQL driver |
1589
- | sync-mysql2 | 1.0.8+ | MySQL driver |
1590
- | better-sqlite3| 12.6.2+ | SQLite driver |
1607
+ | pg | 8.17.2+ | PostgreSQL driver (async) |
1608
+ | mysql2 | 3.11.5+ | MySQL driver (async with connection pooling) |
1609
+ | better-sqlite3| 12.6.2+ | SQLite driver (wrapped with async API) |
1591
1610
 
1592
1611
  ## Documentation
1593
1612
 
@@ -1814,19 +1833,75 @@ $ grep -A1 "catch.*{$" insertManager.js | grep "^\s*}$"
1814
1833
  # ✅ No empty catch blocks - all log errors appropriately
1815
1834
  ```
1816
1835
 
1817
- ### Breaking Changes
1836
+ ### Breaking Changes (v0.3.17+)
1837
+
1838
+ **🔴 CRITICAL: All databases now require async/await for consistency**
1839
+
1840
+ MasterRecord now provides a **unified async API** across all database engines (SQLite, MySQL, PostgreSQL). This follows industry best practices from Sequelize, TypeORM, and Prisma.
1818
1841
 
1819
- **PostgreSQL users must now await `env()`:**
1842
+ **1. Database Operations (All Engines)**
1820
1843
  ```javascript
1821
- // PostgreSQL (async/await REQUIRED):
1844
+ // NEW (v0.3.17+): All databases use async/await
1822
1845
  const db = new AppContext();
1823
- await db.env('./config/environments'); // Must await for PostgreSQL
1846
+ await db.saveChanges(); // Required for SQLite, MySQL, PostgreSQL
1824
1847
 
1825
- // MySQL/SQLite (synchronous - no await):
1826
- const db = new AppContext();
1827
- db.env('./config/environments'); // No await needed for MySQL/SQLite
1848
+ // OLD (v0.3.16 and earlier): Mixed sync/async
1849
+ db.saveChanges(); // SQLite/MySQL were sync (no longer works)
1850
+ await db.saveChanges(); // Only PostgreSQL was async
1828
1851
  ```
1829
1852
 
1853
+ **2. Migration Files (Critical)**
1854
+ ```javascript
1855
+ // ✅ NEW (v0.3.17+): Migrations must be async
1856
+ class CreateUser extends masterrecord.schema {
1857
+ async up(table) { // Must be async
1858
+ this.init(table);
1859
+ await this.createTable(table.User); // Must await
1860
+ }
1861
+
1862
+ async down(table) { // Must be async
1863
+ this.init(table);
1864
+ this.dropTable(table.User);
1865
+ }
1866
+ }
1867
+
1868
+ // ❌ OLD (v0.3.16 and earlier): Migrations were sync
1869
+ up(table) {
1870
+ this.createTable(table.User); // No await (no longer works)
1871
+ }
1872
+ ```
1873
+
1874
+ **3. MySQL Connection**
1875
+ ```javascript
1876
+ // ✅ NEW (v0.3.17+): MySQL uses mysql2/promise with async connection pooling
1877
+ this.env({
1878
+ type: 'mysql',
1879
+ host: 'localhost',
1880
+ port: 3306,
1881
+ database: 'myapp',
1882
+ user: 'root',
1883
+ password: 'password',
1884
+ connectionLimit: 10 // Connection pool size
1885
+ });
1886
+
1887
+ // ❌ OLD (v0.3.16 and earlier): MySQL used sync-mysql2 (synchronous driver)
1888
+ ```
1889
+
1890
+ **Why This Change?**
1891
+ - ✅ **Consistent API**: Same code works for SQLite, MySQL, and PostgreSQL
1892
+ - ✅ **Industry Standard**: Matches Sequelize, TypeORM, Prisma patterns
1893
+ - ✅ **Better Performance**: MySQL now uses connection pooling
1894
+ - ✅ **Real MySQL**: No longer using SQLite disguised as MySQL
1895
+ - ✅ **Portable Code**: Switch databases without code changes
1896
+
1897
+ **Migration Path:**
1898
+ 1. Update all `db.saveChanges()` calls to use `await`
1899
+ 2. Make all migration `up()` and `down()` methods async
1900
+ 3. Add `await` before `createTable()` calls in migrations
1901
+ 4. Update `package.json`: Remove `sync-mysql2`, ensure `mysql2@^3.11.5`
1902
+
1903
+ **For more details, see:** `CHANGES.md`
1904
+
1830
1905
  **For more details, see:** `CHANGES.md`
1831
1906
 
1832
1907
  ---