masterrecord 0.2.6 → 0.2.8
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 +169 -53
- package/Migrations/migrations.js +4 -1
- package/Migrations/schema.js +2 -2
- package/mySQLEngine.js +17 -2
- package/mySQLSyncConnect.js +22 -5
- package/package.json +1 -1
package/Migrations/cli.js
CHANGED
|
@@ -231,49 +231,62 @@ program.option('-V', 'output the version');
|
|
|
231
231
|
var search = `${executedLocation}/**/*${contextFileName}_contextSnapShot.json`;
|
|
232
232
|
var files = globSearch.sync(search, executedLocation);
|
|
233
233
|
var file = files[0];
|
|
234
|
-
if(file){
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
var contextInstance = new context();
|
|
250
|
-
var newMigrationProjectInstance = new migrationProjectFile(context);
|
|
251
|
-
var cleanEntities = migration.cleanEntities(contextInstance.__entities);
|
|
252
|
-
var tableObj = migration.buildUpObject(contextSnapshot.schema, cleanEntities);
|
|
253
|
-
newMigrationProjectInstance.up(tableObj);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
var snap = {
|
|
258
|
-
file : contextSnapshot.contextLocation,
|
|
259
|
-
executedLocation : executedLocation,
|
|
260
|
-
context : contextInstance,
|
|
261
|
-
contextEntities : cleanEntities,
|
|
262
|
-
contextFileName: contextFileName
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
migration.createSnapShot(snap);
|
|
266
|
-
console.log("database updated");
|
|
267
|
-
}
|
|
268
|
-
else{
|
|
234
|
+
if(!file){
|
|
235
|
+
console.log(`Error - Cannot read or find Context snapshot '${contextFileName}_contextSnapShot.json' in '${executedLocation}'.`);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
var contextSnapshot;
|
|
239
|
+
try{
|
|
240
|
+
contextSnapshot = require(file);
|
|
241
|
+
}catch(_){
|
|
242
|
+
console.log(`Error - Cannot read context snapshot at '${file}'.`);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
var searchMigration = `${contextSnapshot.migrationFolder}/**/*_migration.js`;
|
|
246
|
+
var migrationFiles = globSearch.sync(searchMigration, contextSnapshot.migrationFolder);
|
|
247
|
+
if(!(migrationFiles && migrationFiles.length)){
|
|
269
248
|
console.log("Error - Cannot read or find migration file");
|
|
270
|
-
|
|
271
|
-
|
|
249
|
+
return;
|
|
272
250
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
251
|
+
// organize by time using filename timestamp or file mtime
|
|
252
|
+
var mFiles = migrationFiles.slice().sort(function(a, b){
|
|
253
|
+
return __getMigrationTimestamp(a) - __getMigrationTimestamp(b);
|
|
254
|
+
});
|
|
255
|
+
let ContextCtor;
|
|
256
|
+
try{
|
|
257
|
+
ContextCtor = require(contextSnapshot.contextLocation);
|
|
258
|
+
}catch(_){
|
|
259
|
+
console.log(`Error - Cannot load Context file at '${contextSnapshot.contextLocation}'.`);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
var contextInstance;
|
|
263
|
+
try{
|
|
264
|
+
contextInstance = new ContextCtor();
|
|
265
|
+
}catch(_){
|
|
266
|
+
console.log(`Error - Failed to construct Context from '${contextSnapshot.contextLocation}'.`);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
var cleanEntities = migration.cleanEntities(contextInstance.__entities);
|
|
270
|
+
for (let i = 0; i < mFiles.length; i++) {
|
|
271
|
+
var migFile = mFiles[i];
|
|
272
|
+
var migrationProjectFile = require(migFile);
|
|
273
|
+
var newMigrationProjectInstance = new migrationProjectFile(ContextCtor);
|
|
274
|
+
var tableObj = migration.buildUpObject(contextSnapshot.schema, cleanEntities);
|
|
275
|
+
newMigrationProjectInstance.up(tableObj);
|
|
276
|
+
}
|
|
277
|
+
var snap = {
|
|
278
|
+
file : contextSnapshot.contextLocation,
|
|
279
|
+
executedLocation : executedLocation,
|
|
280
|
+
context : contextInstance,
|
|
281
|
+
contextEntities : cleanEntities,
|
|
282
|
+
contextFileName: contextFileName
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
migration.createSnapShot(snap);
|
|
286
|
+
console.log("database updated");
|
|
287
|
+
|
|
288
|
+
}
|
|
289
|
+
catch (e){
|
|
277
290
|
console.log("Error - Cannot read or find file ", e);
|
|
278
291
|
}
|
|
279
292
|
});
|
|
@@ -289,16 +302,27 @@ program.option('-V', 'output the version');
|
|
|
289
302
|
var search = `${executedLocation}/**/*${contextFileName}_contextSnapShot.json`;
|
|
290
303
|
var files = globSearch.sync(search, executedLocation);
|
|
291
304
|
var file = files[0];
|
|
292
|
-
if(file){
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
305
|
+
if(!file){
|
|
306
|
+
console.log(`Error - Cannot read or find Context snapshot '${contextFileName}_contextSnapShot.json' in '${executedLocation}'.`);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
var contextSnapshot;
|
|
310
|
+
try{
|
|
311
|
+
contextSnapshot = require(file);
|
|
312
|
+
}catch(_){
|
|
313
|
+
console.log(`Error - Cannot read context snapshot at '${file}'.`);
|
|
314
|
+
return;
|
|
299
315
|
}
|
|
300
|
-
|
|
301
|
-
|
|
316
|
+
var searchMigration = `${contextSnapshot.migrationFolder}/**/*_migration.js`;
|
|
317
|
+
var migrationFiles = globSearch.sync(searchMigration, contextSnapshot.migrationFolder);
|
|
318
|
+
if(!(migrationFiles && migrationFiles.length)){
|
|
319
|
+
console.log("No migration files found.");
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
var sorted = migrationFiles.slice().sort((a,b) => __getMigrationTimestamp(a) - __getMigrationTimestamp(b));
|
|
323
|
+
// Print relative names for readability
|
|
324
|
+
for(const f of sorted){
|
|
325
|
+
console.log(path.basename(f));
|
|
302
326
|
}
|
|
303
327
|
});
|
|
304
328
|
|
|
@@ -309,10 +333,102 @@ program.option('-V', 'output the version');
|
|
|
309
333
|
.description('Apply pending migrations to database - down method call')
|
|
310
334
|
.action(function(migrationFileName){
|
|
311
335
|
// this will call all the down methods until it gets to the one your looking for. First it needs to validate that there is such a file.
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
336
|
+
var executedLocation = process.cwd();
|
|
337
|
+
var migration = new Migration();
|
|
338
|
+
try{
|
|
339
|
+
// Accept either a bare filename or a path; normalize to basename
|
|
340
|
+
var targetName = path.basename(migrationFileName);
|
|
341
|
+
|
|
342
|
+
// Locate the target migration file anywhere under the current folder
|
|
343
|
+
var searchTarget = `${executedLocation}/**/${targetName}`;
|
|
344
|
+
var targetMatches = globSearch.sync(searchTarget, executedLocation);
|
|
345
|
+
if(!(targetMatches && targetMatches.length)){
|
|
346
|
+
console.log(`Error - Cannot read or find migration file '${targetName}' in '${executedLocation}'.`);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
var targetFilePath = targetMatches[0];
|
|
350
|
+
var migrationFolder = path.dirname(targetFilePath);
|
|
351
|
+
|
|
352
|
+
// Find the context snapshot within the same migrations folder
|
|
353
|
+
var snapshotMatches = globSearch.sync(`${migrationFolder}/**/*_contextSnapShot.json`, migrationFolder);
|
|
354
|
+
var snapshotFile = snapshotMatches && snapshotMatches[0];
|
|
355
|
+
if(!snapshotFile){
|
|
356
|
+
console.log("Error - Cannot read or find Context snapshot in migration folder.");
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
315
359
|
|
|
360
|
+
var contextSnapshot;
|
|
361
|
+
try{
|
|
362
|
+
contextSnapshot = require(snapshotFile);
|
|
363
|
+
}catch(_){
|
|
364
|
+
console.log(`Error - Cannot read context snapshot at '${snapshotFile}'.`);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Get all migration files in this folder
|
|
369
|
+
var allMigrationFiles = globSearch.sync(`${migrationFolder}/**/*_migration.js`, migrationFolder);
|
|
370
|
+
if(!(allMigrationFiles && allMigrationFiles.length)){
|
|
371
|
+
console.log("Error - Cannot read or find migration file");
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Sort chronologically
|
|
376
|
+
var sorted = allMigrationFiles.slice().sort(function(a, b){
|
|
377
|
+
return __getMigrationTimestamp(a) - __getMigrationTimestamp(b);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// Find target index by basename match
|
|
381
|
+
var targetIndex = sorted.findIndex(function(f){ return path.basename(f) === targetName; });
|
|
382
|
+
if(targetIndex === -1){
|
|
383
|
+
console.log(`Error - Target migration '${targetName}' not found.`);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Prepare context and table object
|
|
388
|
+
let ContextCtor;
|
|
389
|
+
try{
|
|
390
|
+
ContextCtor = require(contextSnapshot.contextLocation);
|
|
391
|
+
}catch(_){
|
|
392
|
+
console.log(`Error - Cannot load Context file at '${contextSnapshot.contextLocation}'.`);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
var contextInstance;
|
|
396
|
+
try{
|
|
397
|
+
contextInstance = new ContextCtor();
|
|
398
|
+
}catch(_){
|
|
399
|
+
console.log(`Error - Failed to construct Context from '${contextSnapshot.contextLocation}'.`);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
var cleanEntities = migration.cleanEntities(contextInstance.__entities);
|
|
403
|
+
var tableObj = migration.buildUpObject(contextSnapshot.schema, cleanEntities);
|
|
404
|
+
|
|
405
|
+
// Roll back (down) all migrations newer than the target (i.e., strictly after targetIndex)
|
|
406
|
+
for (var i = sorted.length - 1; i > targetIndex; i--) {
|
|
407
|
+
var migFile = sorted[i];
|
|
408
|
+
var MigCtor = require(migFile);
|
|
409
|
+
var migInstance = new MigCtor(ContextCtor);
|
|
410
|
+
if(typeof migInstance.down === 'function'){
|
|
411
|
+
migInstance.down(tableObj);
|
|
412
|
+
} else {
|
|
413
|
+
console.log(`Warning - Migration '${path.basename(migFile)}' has no down method; skipping.`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Update snapshot
|
|
418
|
+
var snap = {
|
|
419
|
+
file : contextSnapshot.contextLocation,
|
|
420
|
+
executedLocation : executedLocation,
|
|
421
|
+
context : contextInstance,
|
|
422
|
+
contextEntities : cleanEntities,
|
|
423
|
+
contextFileName: path.basename(snapshotFile).replace('_contextSnapShot.json','')
|
|
424
|
+
}
|
|
425
|
+
migration.createSnapShot(snap);
|
|
426
|
+
console.log("database updated");
|
|
427
|
+
|
|
428
|
+
}catch (e){
|
|
429
|
+
console.log("Error - Cannot read or find file ", e);
|
|
430
|
+
}
|
|
431
|
+
});
|
|
316
432
|
|
|
317
433
|
|
|
318
434
|
program.parse(process.argv);
|
package/Migrations/migrations.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// version 0.0.
|
|
1
|
+
// version 0.0.9
|
|
2
2
|
// learn more about seeding info - https://www.pauric.blog/Database-Updates-and-Migrations-with-Entity-Framework/
|
|
3
3
|
|
|
4
4
|
var fs = require('fs');
|
|
@@ -238,6 +238,9 @@ class Migrations{
|
|
|
238
238
|
tables.forEach(function (item, index) {
|
|
239
239
|
// add new columns for table
|
|
240
240
|
var columnInfo = tables[index];
|
|
241
|
+
// Always expose each table under its name so templates like
|
|
242
|
+
// this.createTable(table.TableName) can safely access it.
|
|
243
|
+
tableObj[item.name] = columnInfo.new;
|
|
241
244
|
|
|
242
245
|
item.newTables.forEach(function (column, ind) {
|
|
243
246
|
tableObj[item.name] = columnInfo.new;
|
package/Migrations/schema.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// version 0.0.
|
|
1
|
+
// version 0.0.6
|
|
2
2
|
class schema{
|
|
3
3
|
|
|
4
4
|
constructor(context){
|
|
@@ -85,7 +85,7 @@ class schema{
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
}else{
|
|
88
|
-
console.log("Table that
|
|
88
|
+
console.log("Table that you're trying to create is undefined. Please check if there are any changes that need to be made");
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
package/mySQLEngine.js
CHANGED
|
@@ -570,8 +570,23 @@ class SQLLiteEngine {
|
|
|
570
570
|
|
|
571
571
|
_execute(query){
|
|
572
572
|
console.log("SQL:", query);
|
|
573
|
-
|
|
574
|
-
|
|
573
|
+
try{
|
|
574
|
+
this.db.connect(this.db);
|
|
575
|
+
const res = this.db.query(query);
|
|
576
|
+
if(res === null){
|
|
577
|
+
console.error('MySQL execute skipped: connection not defined');
|
|
578
|
+
return null;
|
|
579
|
+
}
|
|
580
|
+
return res;
|
|
581
|
+
}catch(err){
|
|
582
|
+
const code = err && err.code ? err.code : '';
|
|
583
|
+
if(code === 'ER_BAD_DB_ERROR' || code === 'ECONNREFUSED' || code === 'PROTOCOL_CONNECTION_LOST'){
|
|
584
|
+
console.error('MySQL execute skipped: connection not defined');
|
|
585
|
+
return null;
|
|
586
|
+
}
|
|
587
|
+
console.error(err);
|
|
588
|
+
return null;
|
|
589
|
+
}
|
|
575
590
|
}
|
|
576
591
|
|
|
577
592
|
_run(query){
|
package/mySQLSyncConnect.js
CHANGED
|
@@ -1,28 +1,45 @@
|
|
|
1
|
-
// version : 0.0.
|
|
1
|
+
// version : 0.0.3
|
|
2
2
|
|
|
3
3
|
var MySql = require('sync-mysql2');
|
|
4
4
|
|
|
5
5
|
class MySQLClient {
|
|
6
6
|
constructor(config) {
|
|
7
|
-
this.config = config;
|
|
7
|
+
this.config = config ? { ...config } : {};
|
|
8
|
+
if (this.config && Object.prototype.hasOwnProperty.call(this.config, 'type')) {
|
|
9
|
+
delete this.config.type;
|
|
10
|
+
}
|
|
8
11
|
this.connection = null;
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
connect() {
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
try {
|
|
16
|
+
if (!this.connection) {
|
|
17
|
+
const { type, ...safeConfig } = this.config || {};
|
|
18
|
+
this.connection = new MySql(safeConfig);
|
|
19
|
+
}
|
|
20
|
+
} catch (err) {
|
|
21
|
+
// Swallow connection errors and leave connection undefined so callers can react gracefully
|
|
22
|
+
console.error('MySQL connect error:', err && err.code ? err.code : err);
|
|
23
|
+
this.connection = null;
|
|
24
|
+
return null;
|
|
14
25
|
}
|
|
15
26
|
}
|
|
16
27
|
|
|
17
28
|
query(sql, params = []) {
|
|
18
29
|
try {
|
|
19
30
|
if (!this.connection) {
|
|
20
|
-
|
|
31
|
+
return null;
|
|
21
32
|
}
|
|
22
33
|
var jj = this.connection.query(sql);
|
|
23
34
|
this.connection.finishAll();
|
|
24
35
|
return jj;
|
|
25
36
|
} catch (err) {
|
|
37
|
+
// If the underlying driver surfaces bad DB or network errors, normalize to null
|
|
38
|
+
const code = err && err.code ? err.code : '';
|
|
39
|
+
if(code === 'ER_BAD_DB_ERROR' || code === 'ECONNREFUSED' || code === 'PROTOCOL_CONNECTION_LOST'){
|
|
40
|
+
console.error('MySQL query skipped due to connection not defined');
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
26
43
|
console.error(err);
|
|
27
44
|
return null;
|
|
28
45
|
}
|
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.
|
|
12
|
+
"version": "0.2.8",
|
|
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": {
|