masterrecord 0.2.5 → 0.2.6

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.
package/Migrations/cli.js CHANGED
@@ -21,6 +21,19 @@ var Migration = require('./migrations');
21
21
  var globSearch = require("glob");
22
22
  const pkg = require(path.join(__dirname, '..', 'package.json'));
23
23
 
24
+ // Extract numeric timestamp from migration filename (e.g., 1737999999999_name_migration.js)
25
+ function __getMigrationTimestamp(file){
26
+ try{
27
+ const base = path.basename(file);
28
+ const match = /^([0-9]{10,})_/i.exec(base);
29
+ if(match){ return Number(match[1]); }
30
+ const stat = fs.statSync(file);
31
+ return stat.mtimeMs || 0;
32
+ }catch(_){
33
+ return 0;
34
+ }
35
+ }
36
+
24
37
 
25
38
  const [,, ...args] = process.argv
26
39
 
@@ -45,6 +58,10 @@ program.option('-V', 'output the version');
45
58
  var executedLocation = process.cwd();
46
59
  // find context file from main folder location
47
60
  var contextInstance = migration.findContext(executedLocation, contextFileName);
61
+ if(!contextInstance){
62
+ console.log(`Error - Cannot read or find Context file '${contextFileName}.js' in '${executedLocation}'.`);
63
+ return;
64
+ }
48
65
  var snap = {
49
66
  file : contextInstance.fileLocation,
50
67
  executedLocation : executedLocation,
@@ -103,23 +120,41 @@ program.option('-V', 'output the version');
103
120
  // find context file from main folder location
104
121
  var search = `${executedLocation}/**/*${contextFileName}_contextSnapShot.json`;
105
122
  var files = globSearch.sync(search, executedLocation);
106
- var file = files[0];
107
- if(file){
108
- var contextSnapshot = require(files[0]);
109
- var context = require(contextSnapshot.contextLocation);
110
- var contextInstance = new context();
111
- var cleanEntities = migration.cleanEntities(contextInstance.__entities);
112
- var newEntity = migration.template(name, contextSnapshot.schema, cleanEntities);
113
- var migrationDate = Date.now();
114
- var file = `${contextSnapshot.migrationFolder}/${migrationDate}_${name}_migration.js`
115
- fs.writeFile(file, newEntity, 'utf8', function (err) {
116
- if (err) return console.log("--- Error running cammand, re-run command add-migration ---- ", err);
117
- });
118
- console.log(`${name} migration file created`);
123
+ var file = files && files[0];
124
+ if(!file){
125
+ console.log(`Error - Cannot read or find Context snapshot '${contextFileName}_contextSnapShot.json' in '${executedLocation}'. Run 'masterrecord enable-migrations ${contextFileName}'.`);
126
+ return;
119
127
  }
120
- else{
121
- console.log("Error - Cannot read or find Context file");
128
+ var contextSnapshot = null;
129
+ try{
130
+ contextSnapshot = require(file);
131
+ }catch(_){
132
+ console.log(`Error - Cannot read context snapshot at '${file}'.`);
133
+ return;
122
134
  }
135
+
136
+ let ContextCtor;
137
+ try{
138
+ ContextCtor = require(contextSnapshot.contextLocation);
139
+ }catch(_){
140
+ console.log(`Error - Cannot load Context file at '${contextSnapshot.contextLocation}'.`);
141
+ return;
142
+ }
143
+ let contextInstance;
144
+ try{
145
+ contextInstance = new ContextCtor();
146
+ }catch(_){
147
+ console.log(`Error - Failed to construct Context from '${contextSnapshot.contextLocation}'.`);
148
+ return;
149
+ }
150
+ var cleanEntities = migration.cleanEntities(contextInstance.__entities);
151
+ var newEntity = migration.template(name, contextSnapshot.schema, cleanEntities);
152
+ var migrationDate = Date.now();
153
+ var outputFile = `${contextSnapshot.migrationFolder}/${migrationDate}_${name}_migration.js`
154
+ fs.writeFile(outputFile, newEntity, 'utf8', function (err) {
155
+ if (err) return console.log("--- Error running cammand, re-run command add-migration ---- ", err);
156
+ });
157
+ console.log(`${name} migration file created`);
123
158
  }catch (e){
124
159
  console.log("Error - Cannot read or find file ", e);
125
160
  }
@@ -142,25 +177,20 @@ program.option('-V', 'output the version');
142
177
  var contextSnapshot = require(file);
143
178
  var searchMigration = `${contextSnapshot.migrationFolder}/**/*_migration.js`;
144
179
  var migrationFiles = globSearch.sync(searchMigration, contextSnapshot.migrationFolder);
145
- if( migrationFiles){
146
-
147
- // find newest migration file
148
- // THIS DOESNT WORK BUG - hack to fix this I just take the last file which I am asuming is the newest one
149
- var mFiles = migrationFiles.sort(function(x, y){
150
- return new Date(x.timestamp) < new Date(y.timestamp) ? 1 : -1
151
- });
152
- /** ENd of BUG */
153
-
154
- var mFile = mFiles[mFiles.length -1];
180
+ if( migrationFiles && migrationFiles.length){
181
+ // sort by timestamp prefix or file mtime as fallback
182
+ var mFiles = migrationFiles.slice().sort(function(a, b){
183
+ return __getMigrationTimestamp(a) - __getMigrationTimestamp(b);
184
+ });
185
+ var mFile = mFiles[mFiles.length -1];
155
186
 
156
187
  var migrationProjectFile = require(mFile);
157
188
  var context = require(contextSnapshot.contextLocation);
158
189
  var contextInstance = new context();
159
190
  var newMigrationProjectInstance = new migrationProjectFile(context);
160
191
 
161
- var tableObj = migration.buildUpObject(contextSnapshot.schema, contextInstance.__entities);
162
-
163
- var cleanEntities = migration.cleanEntities(contextInstance.__entities);
192
+ var cleanEntities = migration.cleanEntities(contextInstance.__entities);
193
+ var tableObj = migration.buildUpObject(contextSnapshot.schema, cleanEntities);
164
194
  newMigrationProjectInstance.up(tableObj);
165
195
 
166
196
  var snap = {
@@ -205,12 +235,10 @@ program.option('-V', 'output the version');
205
235
  var contextSnapshot = require(file);
206
236
  var searchMigration = `${contextSnapshot.migrationFolder}/**/*_migration.js`;
207
237
  var migrationFiles = globSearch.sync(searchMigration, contextSnapshot.migrationFolder);
208
- if( migrationFiles){
209
-
210
-
211
- // organize by time
212
- var mFiles = migrationFiles.sort(function(x, y){
213
- return new Date(x.timestamp) < new Date(y.timestamp) ? 1 : -1;
238
+ if( migrationFiles && migrationFiles.length){
239
+ // organize by time using filename timestamp or file mtime
240
+ var mFiles = migrationFiles.slice().sort(function(a, b){
241
+ return __getMigrationTimestamp(a) - __getMigrationTimestamp(b);
214
242
  });
215
243
  var context = require(contextSnapshot.contextLocation);
216
244
 
@@ -220,8 +248,8 @@ program.option('-V', 'output the version');
220
248
 
221
249
  var contextInstance = new context();
222
250
  var newMigrationProjectInstance = new migrationProjectFile(context);
223
- var tableObj = migration.buildUpObject(contextSnapshot.schema, contextInstance.__entities);
224
251
  var cleanEntities = migration.cleanEntities(contextInstance.__entities);
252
+ var tableObj = migration.buildUpObject(contextSnapshot.schema, cleanEntities);
225
253
  newMigrationProjectInstance.up(tableObj);
226
254
  }
227
255
 
@@ -8,10 +8,17 @@ class migrationMySQLQuery {
8
8
  var columnList = [];
9
9
  for (var key in table) {
10
10
  if(typeof table[key] === "object"){
11
- columnList.push(table[key].name);
11
+ var col = table[key];
12
+ // Skip relationship-only fields
13
+ if(col.type === 'hasOne' || col.type === 'hasMany' || col.type === 'hasManyThrough'){
14
+ continue;
15
+ }
16
+ // Map belongsTo to its foreignKey name
17
+ var name = (col.relationshipType === 'belongsTo' && col.foreignKey) ? col.foreignKey : col.name;
18
+ columnList.push(name);
12
19
  }
13
20
  }
14
- return columnList.join(',');;
21
+ return columnList.join(',');
15
22
  }
16
23
 
17
24
  #columnMapping(table){
@@ -8,10 +8,17 @@ class migrationSQLiteQuery {
8
8
  var columnList = [];
9
9
  for (var key in table) {
10
10
  if(typeof table[key] === "object"){
11
- columnList.push(table[key].name);
11
+ var col = table[key];
12
+ // Skip relationship-only fields
13
+ if(col.type === 'hasOne' || col.type === 'hasMany' || col.type === 'hasManyThrough'){
14
+ continue;
15
+ }
16
+ // Map belongsTo to its foreignKey name
17
+ var name = (col.relationshipType === 'belongsTo' && col.foreignKey) ? col.foreignKey : col.name;
18
+ columnList.push(name);
12
19
  }
13
20
  }
14
- return columnList.join(',');;
21
+ return columnList.join(',');
15
22
  }
16
23
 
17
24
  #columnMapping(table){
@@ -134,7 +141,12 @@ class migrationSQLiteQuery {
134
141
  var queryVar = "";
135
142
  for (var key in table) {
136
143
  if(typeof table[key] === "object"){
137
- queryVar += `${this.#columnMapping(table[key])}, `;
144
+ var col = table[key];
145
+ // Skip relationship-only fields
146
+ if(col.type === 'hasOne' || col.type === 'hasMany' || col.type === 'hasManyThrough'){
147
+ continue;
148
+ }
149
+ queryVar += `${this.#columnMapping(col)}, `;
138
150
  }
139
151
  }
140
152
 
@@ -167,7 +167,10 @@ class Migrations{
167
167
  findContext(executedLocation, contextFileName){
168
168
  var search = `${executedLocation}/**/*${contextFileName}.js`
169
169
  var files = globSearch.sync(search, executedLocation);
170
- var file = files[0];
170
+ var file = files && files[0];
171
+ if(!file){
172
+ return null;
173
+ }
171
174
  var context = require(file);
172
175
  return {
173
176
  context : context,
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "app-root-path": "^3.1.0",
10
10
  "better-sqlite3": "^12.4.1"
11
11
  },
12
- "version": "0.2.5",
12
+ "version": "0.2.6",
13
13
  "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 ",
14
14
  "homepage": "https://github.com/Tailor/MasterRecord#readme",
15
15
  "repository": {