masterrecord 0.2.10 → 0.2.12

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
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // version 0.0.6
3
+ // version 0.0.7
4
4
  // https://docs.microsoft.com/en-us/ef/ef6/modeling/code-first/migrations/
5
5
  // how to add environment variables on cli call example - master=development masterrecord add-migration auth authContext
6
6
 
@@ -569,6 +569,85 @@ program.option('-V', 'output the version');
569
569
  });
570
570
 
571
571
 
572
+ program
573
+ .command('update-database-all')
574
+ .alias('uda')
575
+ .description('Scan the project for *Context.js files and run update-database on each')
576
+ .action(function(){
577
+ var executedLocation = process.cwd();
578
+ try{
579
+ // Find all context snapshots and run update per snapshot (avoids unrelated framework contexts)
580
+ var snapshotFiles = globSearch.sync(`${executedLocation}/**/*_contextSnapShot.json`, executedLocation);
581
+ if(!(snapshotFiles && snapshotFiles.length)){
582
+ console.log('No context snapshots found. Run enable-migrations for each context first.');
583
+ return;
584
+ }
585
+ // Group snapshots by context name (case-insensitive) and pick best per group
586
+ var groups = {};
587
+ for(const snapFile of snapshotFiles){
588
+ let cs;
589
+ try{ cs = require(snapFile); }catch(_){ continue; }
590
+ const nameFromPath = path.basename(snapFile).replace(/_contextSnapShot\.json$/i, '').toLowerCase();
591
+ const ctxName = (cs && cs.contextLocation)
592
+ ? path.basename(cs.contextLocation).replace(/\.js$/i, '').toLowerCase()
593
+ : nameFromPath;
594
+ const searchMigration = `${cs.migrationFolder}/**/*_migration.js`;
595
+ const migs = globSearch.sync(searchMigration, cs.migrationFolder) || [];
596
+ if(!groups[ctxName]) groups[ctxName] = [];
597
+ groups[ctxName].push({ snapFile, cs, ctxName, migs });
598
+ }
599
+
600
+ var migration = new Migration();
601
+ var ctxNames = Object.keys(groups);
602
+ for(const name of ctxNames){
603
+ try{
604
+ var list = groups[name];
605
+ // Prefer entries that actually have migration files
606
+ var withMigs = list.filter(e => e.migs && e.migs.length > 0);
607
+ var entry = withMigs.length ? withMigs[withMigs.length - 1] : list[0];
608
+ if(!(entry.migs && entry.migs.length)){
609
+ console.log(`Skipping ${entry.ctxName}: no migration files found.`);
610
+ continue;
611
+ }
612
+ var mFiles = entry.migs.slice().sort(function(a, b){
613
+ return __getMigrationTimestamp(a) - __getMigrationTimestamp(b);
614
+ });
615
+ var mFile = mFiles[mFiles.length - 1];
616
+
617
+ var ContextCtor;
618
+ try{ ContextCtor = require(entry.cs.contextLocation); }catch(_){
619
+ console.log(`Skipping ${entry.ctxName}: cannot load Context at '${entry.cs.contextLocation}'.`);
620
+ continue;
621
+ }
622
+ var contextInstance;
623
+ try{ contextInstance = new ContextCtor(); }catch(_){
624
+ console.log(`Skipping ${entry.ctxName}: failed to construct Context.`);
625
+ continue;
626
+ }
627
+ var migrationProjectFile = require(mFile);
628
+ var newMigrationProjectInstance = new migrationProjectFile(ContextCtor);
629
+ var cleanEntities = migration.cleanEntities(contextInstance.__entities);
630
+ var tableObj = migration.buildUpObject(entry.cs.schema, cleanEntities);
631
+ newMigrationProjectInstance.up(tableObj);
632
+ var snap = {
633
+ file : entry.cs.contextLocation,
634
+ executedLocation : executedLocation,
635
+ context : contextInstance,
636
+ contextEntities : cleanEntities,
637
+ contextFileName: entry.ctxName
638
+ }
639
+ migration.createSnapShot(snap);
640
+ console.log(`database updated for ${entry.ctxName}`);
641
+ }catch(errCtx){
642
+ console.log('Error updating context: ', errCtx);
643
+ }
644
+ }
645
+ }catch(e){
646
+ console.log('Error - Cannot read or find file ', e);
647
+ }
648
+ });
649
+
650
+
572
651
  program.parse(process.argv);
573
652
 
574
653
  // Handle manual '-V' alias
@@ -15,7 +15,7 @@ class migrationMySQLQuery {
15
15
  }
16
16
  // Map belongsTo to its foreignKey name
17
17
  var name = (col.relationshipType === 'belongsTo' && col.foreignKey) ? col.foreignKey : col.name;
18
- columnList.push(name);
18
+ columnList.push(`\`${name}\``);
19
19
  }
20
20
  }
21
21
  return columnList.join(',');
@@ -63,7 +63,7 @@ class migrationMySQLQuery {
63
63
  }
64
64
  }
65
65
 
66
- return `${tableName} ${type}${nullName}${defaultValue}${unique}${primaryKey}${auto}`;
66
+ return `\`${tableName}\` ${type}${nullName}${defaultValue}${unique}${primaryKey}${auto}`;
67
67
  }
68
68
 
69
69
  boolType(type){
@@ -135,7 +135,7 @@ class migrationMySQLQuery {
135
135
 
136
136
  if(table){
137
137
 
138
- return `ALTER TABLE ${table.tableName} MODIFY COLUMN ${this.#columnMapping(table.table)} `;
138
+ return `ALTER TABLE \`${table.tableName}\` MODIFY COLUMN ${this.#columnMapping(table.table)} `;
139
139
  }
140
140
  else{
141
141
  console.log("table information is null");
@@ -152,8 +152,8 @@ class migrationMySQLQuery {
152
152
 
153
153
 
154
154
  addColum(table){
155
- return `ALTER TABLE ${table.tableName}
156
- ADD ${table.name} ${table.realDataType}`;
155
+ return `ALTER TABLE \`${table.tableName}\`
156
+ ADD \`${table.name}\` ${table.realDataType}`;
157
157
 
158
158
  /*
159
159
  column definations
@@ -172,7 +172,7 @@ class migrationMySQLQuery {
172
172
  is indexed
173
173
  appears in a view
174
174
  */
175
- return `ALTER TABLE ${table.tableName} DROP COLUMN ${table.name}`;
175
+ return `ALTER TABLE \`${table.tableName}\` DROP COLUMN \`${table.name}\``;
176
176
  }
177
177
 
178
178
  insertInto(name, table){
@@ -193,7 +193,7 @@ class migrationMySQLQuery {
193
193
  }
194
194
  }
195
195
 
196
- var completeQuery = `CREATE TABLE IF NOT EXISTS ${table.__name} (${queryVar.replace(/,\s*$/, "")});`;
196
+ var completeQuery = `CREATE TABLE IF NOT EXISTS \`${table.__name}\` (${queryVar.replace(/,\s*$/, "")});`;
197
197
  return completeQuery;
198
198
 
199
199
  /*
@@ -213,15 +213,15 @@ class migrationMySQLQuery {
213
213
 
214
214
 
215
215
  dropTable(name){
216
- return `DROP TABLE ${name}`
216
+ return `DROP TABLE \`${name}\``
217
217
  }
218
218
 
219
219
  renameTable(table){
220
- return `ALTER TABLE ${table.tableName} RENAME TO ${table.newName}`;
220
+ return `ALTER TABLE \`${table.tableName}\` RENAME TO \`${table.newName}\``;
221
221
  }
222
222
 
223
223
  renameColumn(table){
224
- return `ALTER TABLE ${table.tableName} RENAME COLUMN ${table.name} TO ${table.newName}`
224
+ return `ALTER TABLE \`${table.tableName}\` RENAME COLUMN \`${table.name}\` TO \`${table.newName}\``
225
225
  }
226
226
 
227
227
 
@@ -356,7 +356,15 @@ class schema{
356
356
  const esc = String(v).replace(/'/g, "''");
357
357
  return `'${esc}'`;
358
358
  }).join(", ");
359
- const sql = `INSERT INTO ${tableName} (${colList}) VALUES (${vals})`;
359
+ // Idempotent seed: ignore duplicates on unique indexes
360
+ let sql;
361
+ if(this.context.isSQLite){
362
+ sql = `INSERT OR IGNORE INTO ${tableName} (${colList}) VALUES (${vals})`;
363
+ } else if(this.context.isMySQL){
364
+ sql = `INSERT IGNORE INTO ${tableName} (${colList}) VALUES (${vals})`;
365
+ } else {
366
+ sql = `INSERT INTO ${tableName} (${colList}) VALUES (${vals})`;
367
+ }
360
368
  this.context._execute(sql);
361
369
  }
362
370
  }
@@ -1,4 +1,4 @@
1
- // version : 0.0.3
1
+ // version : 0.0.4
2
2
 
3
3
  var MySql = require('sync-mysql2');
4
4
 
@@ -60,8 +60,20 @@ class MySQLClient {
60
60
  }
61
61
 
62
62
  close() {
63
- if (this.connection) {
64
- this.connection.end();
63
+ try {
64
+ if (!this.connection) { return; }
65
+ if (typeof this.connection.finishAll === 'function') {
66
+ // Drain any pending RPC calls
67
+ try { this.connection.finishAll(); } catch(_) { /* ignore */ }
68
+ }
69
+ if (typeof this.connection.end === 'function') {
70
+ try { this.connection.end(); } catch(_) { /* ignore */ }
71
+ } else if (typeof this.connection.close === 'function') {
72
+ try { this.connection.close(); } catch(_) { /* ignore */ }
73
+ } else if (typeof this.connection.dispose === 'function') {
74
+ try { this.connection.dispose(); } catch(_) { /* ignore */ }
75
+ }
76
+ } finally {
65
77
  this.connection = null;
66
78
  }
67
79
  }
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.10",
12
+ "version": "0.2.12",
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": {