masterrecord 0.3.60 → 0.3.62

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.
@@ -58,7 +58,7 @@ class Migrations{
58
58
 
59
59
  var table = {
60
60
  name: tableName,
61
- old: null,
61
+ old: {},
62
62
  new :item,
63
63
  newColumns : [],
64
64
  newTables : [],
@@ -75,9 +75,9 @@ class Migrations{
75
75
  var oldItemName = oldItem["__name"];
76
76
  if(table.name === oldItemName){
77
77
  table.old = oldItem;
78
- tables.push(table);
79
78
  }
80
79
  });
80
+ tables.push(table);
81
81
 
82
82
  });
83
83
  }
package/SQLLiteEngine.js CHANGED
@@ -1224,7 +1224,10 @@ class SQLLiteEngine {
1224
1224
  return mainString;;
1225
1225
  }
1226
1226
 
1227
- _execute(query){
1227
+ _execute(query, params){
1228
+ if (params && params.length > 0) {
1229
+ return this._executeWithParams(query, params);
1230
+ }
1228
1231
  if (process.env.LOG_SQL === 'true' || process.env.NODE_ENV !== 'production') {
1229
1232
  console.debug("[SQL]", query);
1230
1233
  }
package/context.js CHANGED
@@ -1824,20 +1824,25 @@ class context {
1824
1824
 
1825
1825
 
1826
1826
  /**
1827
- * Execute a raw SQL query
1827
+ * Execute a raw SQL query, optionally with parameterized values
1828
1828
  *
1829
1829
  * @param {string} query - SQL query to execute
1830
+ * @param {Array} [params] - Optional array of parameter values for placeholders
1830
1831
  *
1831
1832
  * @example
1832
1833
  * context._execute('CREATE INDEX idx_user_email ON User(email)');
1834
+ * context._execute('UPDATE User SET name = ? WHERE id = ?', ['Alice', 1]);
1833
1835
  */
1834
- _execute(query) {
1836
+ _execute(query, params) {
1835
1837
  if (!this._SQLEngine) {
1836
1838
  throw new DatabaseConnectionError(
1837
1839
  'Cannot execute query: database engine not initialized. Ensure you have awaited env() before running queries.',
1838
1840
  this.isMySQL ? 'MySQL' : this.isPostgres ? 'PostgreSQL' : 'SQLite'
1839
1841
  );
1840
1842
  }
1843
+ if (params && params.length > 0) {
1844
+ return this._SQLEngine._execute(query, params);
1845
+ }
1841
1846
  return this._SQLEngine._execute(query);
1842
1847
  }
1843
1848
 
package/mySQLEngine.js CHANGED
@@ -802,8 +802,8 @@ class MySQLEngine {
802
802
  * Execute raw SQL (DDL statements like CREATE TABLE, ALTER TABLE, etc.)
803
803
  * Used by migration schema for non-parameterized DDL queries.
804
804
  */
805
- _execute(query) {
806
- return this._runWithParams(query, []);
805
+ _execute(query, params) {
806
+ return this._runWithParams(query, params || []);
807
807
  }
808
808
 
809
809
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "masterrecord",
3
- "version": "0.3.60",
3
+ "version": "0.3.62",
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/postgresEngine.js CHANGED
@@ -754,8 +754,8 @@ class postgresEngine {
754
754
  * Execute raw SQL (DDL statements like CREATE TABLE, ALTER TABLE, etc.)
755
755
  * Used by migration schema for non-parameterized DDL queries.
756
756
  */
757
- _execute(query) {
758
- return this._runWithParams(query, []);
757
+ _execute(query, params) {
758
+ return this._runWithParams(query, params || []);
759
759
  }
760
760
 
761
761
  async _runWithParams(query, params = []) {
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Test: New entity detection in migrations
3
+ *
4
+ * Verifies that when a new entity is added to a context that already has
5
+ * existing entities (non-empty oldSchema), the migration system correctly
6
+ * includes it in the tables array and detects it as a new table.
7
+ */
8
+
9
+ const path = require('path');
10
+ const Module = require('module');
11
+ const __MASTERRECORD_ROOT__ = path.join(__dirname, '..');
12
+ const __ORIGINAL_REQUIRE__ = Module.prototype.require;
13
+ Module.prototype.require = function(request) {
14
+ if (request === 'masterrecord' || request.startsWith('masterrecord/')) {
15
+ const resolved = request === 'masterrecord'
16
+ ? __MASTERRECORD_ROOT__
17
+ : path.join(__MASTERRECORD_ROOT__, request.slice('masterrecord/'.length));
18
+ return __ORIGINAL_REQUIRE__.call(this, resolved);
19
+ }
20
+ return __ORIGINAL_REQUIRE__.call(this, request);
21
+ };
22
+
23
+ const Migrations = require('../Migrations/migrations');
24
+
25
+ console.log("╔════════════════════════════════════════════════════════════════╗");
26
+ console.log("║ New Entity Migration Detection Test ║");
27
+ console.log("╚════════════════════════════════════════════════════════════════╝\n");
28
+
29
+ let passed = 0;
30
+ let failed = 0;
31
+
32
+ function assert(condition, label) {
33
+ if (condition) {
34
+ console.log(` ✓ ${label}`);
35
+ passed++;
36
+ } else {
37
+ console.log(` ✗ ${label}`);
38
+ failed++;
39
+ }
40
+ }
41
+
42
+ const migration = new Migrations();
43
+
44
+ // Existing entity schema (already in the database)
45
+ const userSchema = {
46
+ __name: 'User',
47
+ id: { name: 'id', type: 'integer', primary: true, auto: true },
48
+ name: { name: 'name', type: 'string' },
49
+ };
50
+
51
+ // New entity schema (being added)
52
+ const customTaskTypeSchema = {
53
+ __name: 'CustomTaskType',
54
+ id: { name: 'id', type: 'integer', primary: true, auto: true },
55
+ label: { name: 'label', type: 'string' },
56
+ };
57
+
58
+ // -----------------------------------------------------------
59
+ // Test 1: First migration (empty oldSchema) — baseline
60
+ // -----------------------------------------------------------
61
+ console.log("Test 1: First migration (empty oldSchema) includes all entities");
62
+ console.log("──────────────────────────────────────────────────");
63
+ {
64
+ const oldSchema = [];
65
+ const newSchema = [userSchema, customTaskTypeSchema];
66
+
67
+ const result = migration.buildUpObject(oldSchema, newSchema);
68
+
69
+ assert(result.User !== undefined, 'User table is in result');
70
+ assert(result.CustomTaskType !== undefined, 'CustomTaskType table is in result');
71
+ }
72
+
73
+ // -----------------------------------------------------------
74
+ // Test 2: Subsequent migration — existing entity still works
75
+ // -----------------------------------------------------------
76
+ console.log("\nTest 2: Subsequent migration — existing entity included");
77
+ console.log("──────────────────────────────────────────────────");
78
+ {
79
+ const oldSchema = [userSchema];
80
+ const newSchema = [userSchema];
81
+
82
+ const result = migration.buildUpObject(oldSchema, newSchema);
83
+
84
+ assert(result.User !== undefined, 'User table is in result');
85
+ }
86
+
87
+ // -----------------------------------------------------------
88
+ // Test 3: Subsequent migration — NEW entity is included (the bug)
89
+ // -----------------------------------------------------------
90
+ console.log("\nTest 3: Subsequent migration — new entity is included");
91
+ console.log("──────────────────────────────────────────────────");
92
+ {
93
+ const oldSchema = [userSchema];
94
+ const newSchema = [userSchema, customTaskTypeSchema];
95
+
96
+ const result = migration.buildUpObject(oldSchema, newSchema);
97
+
98
+ assert(result.User !== undefined, 'User table is in result');
99
+ assert(result.CustomTaskType !== undefined, 'CustomTaskType table is in result (was undefined before fix)');
100
+ }
101
+
102
+ // -----------------------------------------------------------
103
+ // Test 4: hasChanges detects the new entity
104
+ // -----------------------------------------------------------
105
+ console.log("\nTest 4: hasChanges detects new entity");
106
+ console.log("──────────────────────────────────────────────────");
107
+ {
108
+ const oldSchema = [userSchema];
109
+ const newSchema = [userSchema, customTaskTypeSchema];
110
+
111
+ const changed = migration.hasChanges(oldSchema, newSchema);
112
+
113
+ assert(changed === true, 'hasChanges returns true for new entity');
114
+ }
115
+
116
+ // -----------------------------------------------------------
117
+ // Test 5: hasChanges returns false when nothing changed
118
+ // -----------------------------------------------------------
119
+ console.log("\nTest 5: hasChanges returns false when nothing changed");
120
+ console.log("──────────────────────────────────────────────────");
121
+ {
122
+ const oldSchema = [userSchema];
123
+ const newSchema = [userSchema];
124
+
125
+ const changed = migration.hasChanges(oldSchema, newSchema);
126
+
127
+ assert(changed === false, 'hasChanges returns false when schemas are identical');
128
+ }
129
+
130
+ // -----------------------------------------------------------
131
+ // Test 6: Multiple new entities in one migration
132
+ // -----------------------------------------------------------
133
+ console.log("\nTest 6: Multiple new entities in one migration");
134
+ console.log("──────────────────────────────────────────────────");
135
+ {
136
+ const tagSchema = {
137
+ __name: 'Tag',
138
+ id: { name: 'id', type: 'integer', primary: true, auto: true },
139
+ value: { name: 'value', type: 'string' },
140
+ };
141
+
142
+ const oldSchema = [userSchema];
143
+ const newSchema = [userSchema, customTaskTypeSchema, tagSchema];
144
+
145
+ const result = migration.buildUpObject(oldSchema, newSchema);
146
+
147
+ assert(result.User !== undefined, 'User table is in result');
148
+ assert(result.CustomTaskType !== undefined, 'CustomTaskType is in result');
149
+ assert(result.Tag !== undefined, 'Tag is in result');
150
+
151
+ const changed = migration.hasChanges(oldSchema, newSchema);
152
+ assert(changed === true, 'hasChanges detects multiple new entities');
153
+ }
154
+
155
+ // Summary
156
+ console.log("\n" + "=".repeat(64));
157
+ console.log(`Test Results: ${passed} passed, ${failed} failed`);
158
+ console.log("=".repeat(64));
159
+
160
+ if (failed > 0) {
161
+ process.exit(1);
162
+ }