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 +80 -1
- package/Migrations/migrationMySQLQuery.js +10 -10
- package/Migrations/schema.js +9 -1
- package/mySQLSyncConnect.js +15 -3
- package/package.json +1 -1
package/Migrations/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// version 0.0.
|
|
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
|
|
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
|
|
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
|
|
156
|
-
ADD
|
|
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
|
|
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
|
|
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
|
|
216
|
+
return `DROP TABLE \`${name}\``
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
renameTable(table){
|
|
220
|
-
return `ALTER TABLE
|
|
220
|
+
return `ALTER TABLE \`${table.tableName}\` RENAME TO \`${table.newName}\``;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
renameColumn(table){
|
|
224
|
-
return `ALTER TABLE
|
|
224
|
+
return `ALTER TABLE \`${table.tableName}\` RENAME COLUMN \`${table.name}\` TO \`${table.newName}\``
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
|
package/Migrations/schema.js
CHANGED
|
@@ -356,7 +356,15 @@ class schema{
|
|
|
356
356
|
const esc = String(v).replace(/'/g, "''");
|
|
357
357
|
return `'${esc}'`;
|
|
358
358
|
}).join(", ");
|
|
359
|
-
|
|
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
|
}
|
package/mySQLSyncConnect.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// version : 0.0.
|
|
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
|
-
|
|
64
|
-
this.connection
|
|
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.
|
|
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": {
|