masterrecord 0.0.26 → 0.0.28
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/Masterrecord.js +73 -26
- package/Migrations/cli.js +77 -50
- package/Migrations/migrationTemplate.js +65 -50
- package/Migrations/migrations.js +160 -43
- package/Migrations/schema.js +24 -3
- package/Tools.js +11 -0
- package/package.json +6 -4
- package/readme.md +1 -0
package/Masterrecord.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
// https://github.com/kriasoft/node-sqlite
|
|
3
3
|
// https://www.learnentityframeworkcore.com/dbset/deleting-data
|
|
4
|
-
// version 1.0.
|
|
4
|
+
// version 1.0.16
|
|
5
5
|
|
|
6
6
|
var modelBuilder = require('./Entity/EntityModelBuilder');
|
|
7
7
|
var query = require('masterrecord/QueryLanguage/queryMethods');
|
|
@@ -10,6 +10,8 @@ var SQLLiteEngine = require('masterrecord/SQLLiteEngine');
|
|
|
10
10
|
var MYSQLEngine = require('masterrecord/MYSQLEngine');
|
|
11
11
|
var insertManager = require('./InsertManager');
|
|
12
12
|
var deleteManager = require('./DeleteManager');
|
|
13
|
+
var globSearch = require("glob");
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
class Context {
|
|
15
17
|
_isModelValid = {
|
|
@@ -20,12 +22,13 @@ class Context {
|
|
|
20
22
|
__builderEntities = [];
|
|
21
23
|
__trackedEntities = [];
|
|
22
24
|
__relationshipModels = [];
|
|
25
|
+
__enviornment = "";
|
|
26
|
+
__name = "";
|
|
23
27
|
|
|
24
28
|
constructor(){
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this._SQLEngine = "";
|
|
29
|
+
this. __enviornment = process.env.master;
|
|
28
30
|
this.__name = this.constructor.name;
|
|
31
|
+
this._SQLEngine = "";
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
/*
|
|
@@ -40,7 +43,8 @@ class Context {
|
|
|
40
43
|
__SQLiteInit(env, sqlName){
|
|
41
44
|
try{
|
|
42
45
|
const sqlite3 = require(sqlName);
|
|
43
|
-
|
|
46
|
+
console.log("sdsdsds", env)
|
|
47
|
+
let DBAddress = env.completeConnection;
|
|
44
48
|
var db = new sqlite3(DBAddress, env);
|
|
45
49
|
db.__name = sqlName;
|
|
46
50
|
this._SQLEngine = new SQLLiteEngine();
|
|
@@ -84,35 +88,78 @@ class Context {
|
|
|
84
88
|
errors: []
|
|
85
89
|
};
|
|
86
90
|
};
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
91
|
+
|
|
92
|
+
__findSettings(root, rootFolderLocation, envType){
|
|
93
|
+
|
|
94
|
+
var rootFolder = `${root}/${rootFolderLocation}`;
|
|
95
|
+
var search = `${rootFolder}/**/*env.${envType}.json`;
|
|
96
|
+
var files = globSearch.sync(search, rootFolder);
|
|
97
|
+
var file = files[0];
|
|
98
|
+
if(file === undefined){
|
|
99
|
+
root = tools.removeBackwardSlashSection(root, 1, "/");
|
|
100
|
+
rootFolder = `${root}/${rootFolderLocation}`;
|
|
101
|
+
var search = `${rootFolder}/**/*env.${envType}.json`;
|
|
102
|
+
var files = globSearch.sync(search,rootFolder);
|
|
103
|
+
file = files[0];
|
|
104
|
+
if(file === undefined){
|
|
105
|
+
root = tools.removeBackwardSlashSection(root, 1, "/");
|
|
106
|
+
rootFolder = `${root}/${rootFolderLocation}`;
|
|
107
|
+
var search = `${rootFolder}/**/*env.${envType}.json`;
|
|
108
|
+
var files = globSearch.sync(search,rootFolder);
|
|
109
|
+
file = files[0];
|
|
110
|
+
if(file === undefined){
|
|
111
|
+
console.log(`could not find file - ${rootFolder}/env.${envType}.json`);
|
|
112
|
+
throw error(`could not find file - ${rootFolder}/env.${envType}.json`);
|
|
104
113
|
}
|
|
114
|
+
|
|
105
115
|
}
|
|
106
|
-
|
|
107
|
-
|
|
116
|
+
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
file: file,
|
|
121
|
+
rootFolder : root
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
useSqlite(rootFolderLocation){
|
|
126
|
+
var root = process.cwd();
|
|
127
|
+
var envType = this.__enviornment;
|
|
128
|
+
var contextName = this.__name;
|
|
129
|
+
var file = this.__findSettings(root, rootFolderLocation, envType);
|
|
130
|
+
var settings = require(file.file);
|
|
131
|
+
var options = settings[contextName];
|
|
132
|
+
if(options === undefined){
|
|
133
|
+
console.log("settings missing context name settings");
|
|
134
|
+
throw error("settings missing context name settings");
|
|
108
135
|
}
|
|
136
|
+
this.validateSQLiteOptions(options);
|
|
137
|
+
options.completeConnection = `${file.rootFolder}${options.connection}`;
|
|
138
|
+
this.db = this.__SQLiteInit(options, "better-sqlite3");
|
|
139
|
+
this._SQLEngine.setDB(this.db, "better-sqlite3");
|
|
140
|
+
return this;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
validateSQLiteOptions(options){
|
|
144
|
+
if(options.hasOwnProperty('connect') === undefined){
|
|
145
|
+
console.log("connnect string settings is missing")
|
|
146
|
+
throw error("connection string settings is missing");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
useMySql(options, rootFolderLocation){
|
|
152
|
+
if(options !== undefined){
|
|
153
|
+
this.db = this.__mysqlInit(options, "mysql");
|
|
154
|
+
this._SQLEngine.setDB(this.db, "mysql");
|
|
155
|
+
return this;
|
|
109
156
|
}
|
|
110
157
|
else{
|
|
111
|
-
console.log("database
|
|
158
|
+
console.log("database options not defined - Master Record");
|
|
112
159
|
}
|
|
113
|
-
|
|
114
160
|
}
|
|
115
161
|
|
|
162
|
+
|
|
116
163
|
dbset(model, name){
|
|
117
164
|
var validModel = modelBuilder.create(model);
|
|
118
165
|
validModel.__name = name === undefined ? model.name : name;
|
package/Migrations/cli.js
CHANGED
|
@@ -4,82 +4,108 @@ const program = require('commander');
|
|
|
4
4
|
let fs = require('fs');
|
|
5
5
|
let path = require('path');
|
|
6
6
|
var Migration = require('./migrations');
|
|
7
|
+
var globSearch = require("glob");
|
|
7
8
|
|
|
8
9
|
const [,, ...args] = process.argv
|
|
9
10
|
|
|
11
|
+
|
|
12
|
+
|
|
10
13
|
program
|
|
11
|
-
.version('0.0.
|
|
12
|
-
.option('-v, --version', '0.0.
|
|
14
|
+
.version('0.0.2')
|
|
15
|
+
.option('-v, --version', '0.0.2')
|
|
13
16
|
.description('A ORM framework that facilitates the creation and use of business objects whose data requires persistent storage to a database');
|
|
14
17
|
|
|
15
|
-
// Instructions : to run command you must go to
|
|
18
|
+
// Instructions : to run command you must go to main project folder is located and run the command using the context file name.
|
|
16
19
|
program
|
|
17
20
|
.command('enable-migrations <contextFileName>')
|
|
18
|
-
.alias('
|
|
19
|
-
.description('Enables the migration in your project by creating a
|
|
21
|
+
.alias('em')
|
|
22
|
+
.description('Enables the migration in your project by creating a configuration class called ContextSnapShot.json')
|
|
20
23
|
.action(function(contextFileName){
|
|
24
|
+
|
|
25
|
+
var migration = new Migration();
|
|
21
26
|
// location of folder where command is being executed..
|
|
22
27
|
var executedLocation = process.cwd();
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
// find context file from main folder location
|
|
29
|
+
var contextInstance = migration.getContext(executedLocation, contextFileName);
|
|
30
|
+
|
|
31
|
+
var snap = {
|
|
32
|
+
file : contextInstance.fileLocation,
|
|
33
|
+
executedLocation : executedLocation,
|
|
34
|
+
context : new contextInstance.context({
|
|
35
|
+
root: executedLocation
|
|
36
|
+
}),
|
|
37
|
+
contextFileName: contextFileName.toLowerCase()
|
|
28
38
|
}
|
|
29
39
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
schema : {}
|
|
34
|
-
};
|
|
35
|
-
const jsonContent = JSON.stringify(content, null, 2);
|
|
36
|
-
try{
|
|
37
|
-
// will replace the whole file if it exist
|
|
38
|
-
fs.writeFileSync(`${migrationsDirectory}/ContextSnapShot.json`, jsonContent);
|
|
39
|
-
}catch (e){
|
|
40
|
-
console.log("Cannot write file ", e);
|
|
41
|
-
}
|
|
40
|
+
migration.createSnapShot(snap);
|
|
41
|
+
console.log("Migration enabled")
|
|
42
|
+
|
|
42
43
|
});
|
|
43
44
|
|
|
44
45
|
// Instructions : to run command you must go to folder where migration file is located.
|
|
45
46
|
program
|
|
46
|
-
.command('add-migration <name>')
|
|
47
|
+
.command('add-migration <name> <contextFileName>')
|
|
47
48
|
.alias('am')
|
|
48
|
-
.
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
.action(function(name, contextFileName){
|
|
50
|
+
var executedLocation = process.cwd();
|
|
51
|
+
contextFileName = contextFileName.toLowerCase();
|
|
52
|
+
var migration = new Migration();
|
|
51
53
|
try{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
// find context file from main folder location
|
|
55
|
+
var search = `${executedLocation}/**/*${contextFileName}_contextSnapShot.json`;
|
|
56
|
+
|
|
57
|
+
var files = globSearch.sync(search, executedLocation);
|
|
58
|
+
var contextSnapshot = require(files[0]);
|
|
59
|
+
var context = require(contextSnapshot.contextLocation);
|
|
60
|
+
var contextInstance = new context();
|
|
61
|
+
var newEntity = migration.buildMigrationTemplate(name, contextSnapshot.schema, contextInstance .__entities);
|
|
62
|
+
var migrationDate = Date.now();
|
|
63
|
+
var file = `${contextSnapshot.migrationFolder}/${migrationDate}_${name}_migration.js`
|
|
64
|
+
fs.writeFile(file, newEntity, 'utf8', function (err) {
|
|
65
|
+
if (err) return console.log("--- Error running cammand, rlease run command add-migration ---- ", err);
|
|
66
|
+
|
|
67
|
+
});
|
|
68
|
+
}catch (e){
|
|
69
|
+
console.log("Cannot read or find file ", e);
|
|
63
70
|
}
|
|
64
71
|
|
|
72
|
+
console.log(`${name} migration file created`);
|
|
65
73
|
});
|
|
66
74
|
|
|
67
|
-
// will use the database settings to call and get the schema_migration table
|
|
68
|
-
// we will get the list of all migrations that have been ran
|
|
69
|
-
// we will compare that list with the folder of migrations to see if we ran everything
|
|
70
|
-
// the migrations we missed we will call the up method
|
|
71
|
-
// the up method will run the create database functions
|
|
72
|
-
// then update the database.js schema
|
|
73
|
-
|
|
74
75
|
program
|
|
75
|
-
.command('update-database <
|
|
76
|
+
.command('update-database <contextFileName> <environment>')
|
|
76
77
|
.alias('ud')
|
|
77
78
|
.description('Apply pending migrations to database')
|
|
78
|
-
.action(function(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
.action(function(contextFileName, environment){
|
|
80
|
+
console.log("NODE_ENV", process.NODE_ENV)
|
|
81
|
+
var executedLocation = process.cwd();
|
|
82
|
+
contextFileName = contextFileName.toLowerCase();
|
|
83
|
+
|
|
84
|
+
try{
|
|
85
|
+
// find context file from main folder location
|
|
86
|
+
var search = `${executedLocation}/**/*${contextFileName}_contextSnapShot.json`;
|
|
87
|
+
var files = globSearch.sync(search, executedLocation);
|
|
88
|
+
var file = files[0];
|
|
89
|
+
var contextSnapshot = require(file);
|
|
90
|
+
|
|
91
|
+
var searchMigration = `**/*_migration.js`;
|
|
92
|
+
var migrationFiles = globSearch.sync(searchMigration, contextSnapshot.migrationFolder);
|
|
93
|
+
if( migrationFiles){
|
|
94
|
+
// find newest migration file
|
|
95
|
+
var mFiles = migrationFiles.sort(function(x, y){
|
|
96
|
+
return new Date(x.timestamp) < new Date(y.timestamp) ? 1 : -1
|
|
97
|
+
});
|
|
98
|
+
mFiles = mFiles[0];
|
|
99
|
+
var migration = require(mFiles);
|
|
100
|
+
var context = require(contextSnapshot.contextLocation);
|
|
101
|
+
var contextInstance = new context();
|
|
102
|
+
var newMigrationInstance = new migration(context);
|
|
103
|
+
newMigrationInstance.up();
|
|
104
|
+
}
|
|
105
|
+
}catch (e){
|
|
106
|
+
console.log("Cannot read or find file ", e);
|
|
107
|
+
}
|
|
108
|
+
console.log("database updated");
|
|
83
109
|
});
|
|
84
110
|
|
|
85
111
|
// we will find the migration folder inside the nearest app folder if no migration folder is location is added
|
|
@@ -88,6 +114,7 @@ program
|
|
|
88
114
|
.alias('rm')
|
|
89
115
|
.description('Removes the last migration that has not been applied')
|
|
90
116
|
.action(function(name){
|
|
117
|
+
// remove migrations call the down method of a migration newMigrationInstance.down();
|
|
91
118
|
// find migration file using name and delete it.
|
|
92
119
|
});
|
|
93
120
|
|
|
@@ -1,64 +1,79 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
const os = require('os');
|
|
3
2
|
|
|
4
3
|
// https://channel9.msdn.com/Blogs/EF/Migrations-Under-the-Hood
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// the EDMModelDiffer function to calculate database changes
|
|
12
|
-
// EDMModelDiffer will return only database changes model that have not been implemented already
|
|
13
|
-
// we then create the miration using function 'migrationCodeGenerator' based on the model that was provided by EDMModelDiffer
|
|
14
|
-
// js date stamp Date.now()
|
|
15
|
-
|
|
16
|
-
class Migration extends Schema {
|
|
17
|
-
|
|
18
|
-
constructor() {
|
|
19
|
-
super();
|
|
5
|
+
class MigrationTemplate {
|
|
6
|
+
up = ''
|
|
7
|
+
down = ''
|
|
8
|
+
constructor(name) {
|
|
9
|
+
this.name = name;
|
|
20
10
|
}
|
|
21
11
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
unique : true,
|
|
29
|
-
nullable : false
|
|
30
|
-
},
|
|
31
|
-
user_id : {
|
|
32
|
-
type : "integer",
|
|
33
|
-
required : true, // SQL Data Constraints
|
|
34
|
-
foreignKey : "user" // SQL Data Constraints
|
|
35
|
-
},
|
|
36
|
-
website_url : {
|
|
37
|
-
type : "string",
|
|
38
|
-
required : true,
|
|
39
|
-
maxLength : 60
|
|
40
|
-
},
|
|
41
|
-
website_type : {
|
|
42
|
-
type : "string",
|
|
43
|
-
required : true
|
|
44
|
-
}
|
|
45
|
-
});
|
|
12
|
+
get(){
|
|
13
|
+
return `
|
|
14
|
+
class ${this.name} extends Schema {
|
|
15
|
+
constructor(context){
|
|
16
|
+
super(context);
|
|
17
|
+
}
|
|
46
18
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
});
|
|
19
|
+
up(table){
|
|
20
|
+
${this.up}
|
|
21
|
+
}
|
|
51
22
|
|
|
52
|
-
|
|
23
|
+
down(table){
|
|
24
|
+
${this.down}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
module.exports = ${this.name};
|
|
28
|
+
`
|
|
53
29
|
}
|
|
54
30
|
|
|
55
|
-
|
|
56
|
-
|
|
31
|
+
alterColumn(){
|
|
32
|
+
if(type === "up"){
|
|
33
|
+
this.up += os.EOL + ` this.alterColumn(table.name, table.column);`
|
|
34
|
+
}
|
|
35
|
+
else{
|
|
36
|
+
this.down += os.EOL + ` this.alterColumn(table.name, table.column);`
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
createTable(){
|
|
40
|
+
if(type === "up"){
|
|
41
|
+
this.up += os.EOL + ` this.createTable(table.name);`
|
|
42
|
+
}
|
|
43
|
+
else{
|
|
44
|
+
this.down += os.EOL + ` this.createTable(table.name);`
|
|
45
|
+
}
|
|
46
|
+
}
|
|
57
47
|
|
|
58
|
-
|
|
48
|
+
addColumn(type){
|
|
49
|
+
if(type === "up"){
|
|
50
|
+
this.up += os.EOL + ` this.addColumn(table.name, table.column);`
|
|
51
|
+
}
|
|
52
|
+
else{
|
|
53
|
+
this.down += os.EOL + ` this.addColumn(table.name, table.column);`
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
dropTable(type){
|
|
59
|
+
if(type === "up"){
|
|
60
|
+
this.down += os.EOL + ` this.droptable(table.name);`
|
|
61
|
+
}
|
|
62
|
+
else{
|
|
63
|
+
this.down += os.EOL + ` this.droptable(table.name);`
|
|
64
|
+
}
|
|
65
|
+
}
|
|
59
66
|
|
|
60
|
-
|
|
67
|
+
dropColumn(type){
|
|
68
|
+
if(type === "up"){
|
|
69
|
+
this.up += os.EOL + ` this.dropColumn(table.name, table.column);`
|
|
70
|
+
}
|
|
71
|
+
else{
|
|
72
|
+
this.down += os.EOL + ` this.dropColumn(table.name, table.column);`
|
|
73
|
+
}
|
|
61
74
|
}
|
|
75
|
+
|
|
62
76
|
}
|
|
63
77
|
|
|
64
|
-
module.exports =
|
|
78
|
+
module.exports = MigrationTemplate;
|
|
79
|
+
|
package/Migrations/migrations.js
CHANGED
|
@@ -1,57 +1,174 @@
|
|
|
1
|
-
// version
|
|
1
|
+
// version 0.0.3
|
|
2
|
+
// learn more about seeding info - https://www.pauric.blog/Database-Updates-and-Migrations-with-Entity-Framework/
|
|
3
|
+
|
|
2
4
|
var fs = require('fs');
|
|
5
|
+
var diff = require("deep-object-diff");
|
|
6
|
+
var MigrationTemplate = require("./migrationTemplate");
|
|
7
|
+
var globSearch = require("glob");
|
|
8
|
+
|
|
3
9
|
// https://blog.tekspace.io/code-first-multiple-db-context-migration/
|
|
4
10
|
|
|
5
11
|
// node masterrecord add-migration josh C:\Users\rbatista\Downloads\kollege\freshmen\app\models\context
|
|
6
12
|
class Migrations{
|
|
7
13
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
// loop through tables
|
|
19
|
-
for (const columnKey of columnKeyList) {
|
|
20
|
-
var newTable = {};
|
|
21
|
-
if(tableSnapShot[columnKey]){
|
|
22
|
-
|
|
23
|
-
/*
|
|
24
|
-
id : {
|
|
25
|
-
nullabale : true,
|
|
26
|
-
type : string
|
|
27
|
-
}
|
|
14
|
+
getContext(executedLocation, contextFileName){
|
|
15
|
+
var search = `${executedLocation}/**/*${contextFileName}.js`
|
|
16
|
+
var files = globSearch.sync(search, executedLocation);
|
|
17
|
+
var file = files[0];
|
|
18
|
+
var context = require(file);
|
|
19
|
+
return {
|
|
20
|
+
context : context,
|
|
21
|
+
fileLocation : file
|
|
22
|
+
}
|
|
23
|
+
}
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
25
|
+
createSnapShot(snap){
|
|
26
|
+
var migrationsDirectory = `${snap.executedLocation}/db/migrations`;
|
|
27
|
+
if (!fs.existsSync(migrationsDirectory)){
|
|
28
|
+
fs.mkdirSync(migrationsDirectory);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
var content = {
|
|
32
|
+
seed : function(seed){
|
|
33
|
+
this.seed(this);
|
|
34
|
+
},
|
|
35
|
+
contextLocation: snap.file,
|
|
36
|
+
migrationFolder: `${snap.executedLocation}/db/migrations`,
|
|
37
|
+
snapShotLocation: `${snap.executedLocation}/db/migrations/${snap.contextFileName}_contextSnapShot.json`,
|
|
38
|
+
schema : snap.context.__entities
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const jsonContent = JSON.stringify(content, null, 2);
|
|
42
|
+
try{
|
|
43
|
+
// will replace the whole file if it exist
|
|
44
|
+
fs.writeFileSync(`${migrationsDirectory}/${snap.contextFileName}_contextSnapShot.json`, jsonContent);
|
|
45
|
+
}catch (e){
|
|
46
|
+
console.log("Cannot write file ", e);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
organizeSchemaByTables(oldSchema, newSchema){
|
|
51
|
+
var tables = []
|
|
52
|
+
|
|
53
|
+
newSchema.forEach(function (item, index) {
|
|
54
|
+
|
|
55
|
+
var table = {
|
|
56
|
+
name: item["__name"],
|
|
57
|
+
old: null,
|
|
58
|
+
new :item,
|
|
59
|
+
newColumns : [],
|
|
60
|
+
deletedColumns : [],
|
|
61
|
+
updatedColumns : []
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
oldSchema.forEach(function (oldItem, index) {
|
|
65
|
+
var oldItemName = oldItem["__name"];
|
|
66
|
+
if(table.name === oldItemName){
|
|
67
|
+
table.old = oldItem;
|
|
68
|
+
tables.push(table);
|
|
42
69
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return tables;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
findDeletedColumnsInTables(tables){
|
|
77
|
+
tables.forEach(function (item, index) {
|
|
78
|
+
var deletedColumn = null;
|
|
79
|
+
if(item.new && item.old){
|
|
80
|
+
Object.keys(item.old).forEach(function (key) {
|
|
81
|
+
var value = item.old[key].name;
|
|
82
|
+
deletedColumn = null;
|
|
83
|
+
Object.keys(item.new).forEach(function (newKey) {
|
|
84
|
+
var newValue = item.new[newKey].name;
|
|
85
|
+
if(value === newValue){
|
|
86
|
+
deletedColumn = value;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
if(deletedColumn === null){
|
|
90
|
+
item.deletedColumns.push(value);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
48
93
|
}
|
|
49
|
-
}
|
|
50
|
-
|
|
94
|
+
});
|
|
95
|
+
return tables;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
findUpdatedColumns(tables){
|
|
99
|
+
tables.forEach(function (item, index) {
|
|
100
|
+
var UD = diff.updatedDiff(item.old, item.new);
|
|
101
|
+
const isEmpty = Object.keys(UD).length === 0;
|
|
102
|
+
if(!isEmpty){
|
|
103
|
+
item.updatedColumns.push(diff.updatedDiff(item.old, item.new));
|
|
51
104
|
}
|
|
52
|
-
|
|
53
105
|
|
|
54
|
-
}
|
|
106
|
+
});
|
|
107
|
+
return tables;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
findNewColumnsInTables(tables){
|
|
111
|
+
tables.forEach(function (item, index) {
|
|
112
|
+
var newColumn = null;
|
|
113
|
+
if(item.new && item.old){
|
|
114
|
+
Object.keys(item.new).forEach(function (key) {
|
|
115
|
+
var value = item.new[key].name;
|
|
116
|
+
newColumn = null;
|
|
117
|
+
Object.keys(item.old).forEach(function (oldKey) {
|
|
118
|
+
var oldValue = item.old[oldKey].name;
|
|
119
|
+
if(value === oldValue){
|
|
120
|
+
newColumn = value;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
if(newColumn === null){
|
|
124
|
+
item.newColumns.push(value);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return tables;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
buildMigrationTemplate(name, oldSchema, newSchema){
|
|
134
|
+
|
|
135
|
+
var MT = new MigrationTemplate(name);
|
|
136
|
+
var tables = this.organizeSchemaByTables(oldSchema, newSchema);
|
|
137
|
+
tables = this.findNewColumnsInTables(tables);
|
|
138
|
+
tables = this.findDeletedColumnsInTables(tables);
|
|
139
|
+
tables = this.findUpdatedColumns(tables);
|
|
140
|
+
tables.forEach(function (item, index) {
|
|
141
|
+
// add new columns for table
|
|
142
|
+
item.newColumns.forEach(function (column, index) {
|
|
143
|
+
MT.addColumn();
|
|
144
|
+
MT.dropColumn("down");
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
item.deletedColumns.forEach(function (column, index) {
|
|
148
|
+
MT.dropColumn("up");
|
|
149
|
+
MT.addColumn("down");
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
item.updatedColumns.forEach(function (column, index) {
|
|
153
|
+
MT.alterColumn();
|
|
154
|
+
MT.alterColumn("down")
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
if(item.old === null){
|
|
158
|
+
MT.createTable();
|
|
159
|
+
MT.dropTable("down");
|
|
160
|
+
|
|
161
|
+
}
|
|
162
|
+
if(item.new === null){
|
|
163
|
+
MT.dropTable("up");
|
|
164
|
+
MT.createTable("down");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
return MT.get();
|
|
170
|
+
|
|
171
|
+
|
|
55
172
|
}
|
|
56
173
|
|
|
57
174
|
migrationCodeGenerator(name, column, migrationDate){
|
package/Migrations/schema.js
CHANGED
|
@@ -2,23 +2,43 @@
|
|
|
2
2
|
var fs = require('fs');
|
|
3
3
|
|
|
4
4
|
class Schema{
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
constructor(settings){
|
|
7
|
+
this.settings = settings;
|
|
8
|
+
}
|
|
9
|
+
|
|
6
10
|
// create obj to convert into create sql
|
|
7
11
|
addColumn(tableName, columnName, ){
|
|
8
12
|
|
|
9
13
|
// add column to database
|
|
10
14
|
}
|
|
11
15
|
|
|
16
|
+
createTable(name, columns){
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
dropColumn(tableName, columnName){
|
|
13
21
|
// drop column
|
|
14
22
|
|
|
15
23
|
}
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
dropTable(name){
|
|
18
26
|
|
|
19
27
|
}
|
|
20
28
|
|
|
21
|
-
|
|
29
|
+
dropIndex(){
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
//"dbo.People", "Location"
|
|
33
|
+
alterColumn(){
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
renameColumn(){
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
seed(){
|
|
22
42
|
|
|
23
43
|
}
|
|
24
44
|
|
|
@@ -27,6 +47,7 @@ class Schema{
|
|
|
27
47
|
|
|
28
48
|
|
|
29
49
|
}
|
|
50
|
+
|
|
30
51
|
}
|
|
31
52
|
|
|
32
53
|
|
package/Tools.js
CHANGED
|
@@ -4,6 +4,17 @@ class Tools{
|
|
|
4
4
|
return entityList[name];
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
|
|
8
|
+
// this will remove everthing from back slash amount
|
|
9
|
+
static removeBackwardSlashSection(string, amount, type){
|
|
10
|
+
type = type === undefined ? "\\" : type;
|
|
11
|
+
var stringArray = string.split(type);
|
|
12
|
+
for(var i = 0; i < amount; i++){
|
|
13
|
+
stringArray.pop();
|
|
14
|
+
}
|
|
15
|
+
return stringArray.join(type);
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
static removePrimarykeyandVirtual(currentModel, modelEntity){
|
|
8
19
|
var newCurrentModel = Object.create(currentModel);
|
|
9
20
|
|
package/package.json
CHANGED
|
@@ -2,22 +2,24 @@
|
|
|
2
2
|
"name": "masterrecord",
|
|
3
3
|
"dependencies": {
|
|
4
4
|
"better-sqlite3": "^7.6.2",
|
|
5
|
-
"commander": "^9.4.0"
|
|
5
|
+
"commander": "^9.4.0",
|
|
6
|
+
"glob" : "^8.0.3",
|
|
7
|
+
"deep-object-diff" : "^1.1.7"
|
|
6
8
|
},
|
|
7
|
-
"version": "0.0.
|
|
9
|
+
"version": "0.0.28",
|
|
8
10
|
"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 ",
|
|
9
11
|
"homepage": "https://github.com/Tailor/MasterRecord#readme",
|
|
10
12
|
"repository": {
|
|
11
13
|
"type": "git",
|
|
12
14
|
"url": "git+https://github.com/Tailor/Masterrecord.git"
|
|
13
15
|
},
|
|
14
|
-
"main": "./
|
|
16
|
+
"main": "./migrations/cli.js",
|
|
15
17
|
"scripts": {
|
|
16
18
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
17
19
|
},
|
|
18
20
|
"author": "Alexander Rich",
|
|
19
21
|
"license": "ISC",
|
|
20
22
|
"bin": {
|
|
21
|
-
"masterrecord": "migrations/cli.js"
|
|
23
|
+
"masterrecord": "./migrations/cli.js"
|
|
22
24
|
}
|
|
23
25
|
}
|
package/readme.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
local install of CLI package run code in terminal - "npm install -g ./"
|