masterrecord 0.0.24 → 0.0.26

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.
@@ -0,0 +1,51 @@
1
+ var tools = require('./Tools');
2
+
3
+ class DeleteManager{
4
+ constructor(sqlEngine, entities){
5
+ this._SQLEngine = sqlEngine;
6
+ this._allEntities = entities;
7
+ }
8
+
9
+ init(currentModel){
10
+ var $that = this;
11
+ try{
12
+ this.cascadeDelete(currentModel);
13
+ }
14
+ catch(error){
15
+ throw error;
16
+ }
17
+ }
18
+
19
+ cascadeDelete(currentModel){
20
+ var $that = this;
21
+ if(!Array.isArray(currentModel)){
22
+ const entityKeys = Object.keys(currentModel.__entity);
23
+ // loop though all entity properties
24
+ for (const property of entityKeys) {
25
+ // cascade delete
26
+ if(currentModel.__entity[property].type === "hasOne" || currentModel.__entity[property].type === "hasMany"){
27
+ $that.cascadeDelete( currentModel[property]);
28
+ }
29
+ }
30
+ this._SQLEngine.delete(currentModel);
31
+ }
32
+ else{
33
+
34
+ for(let i = 0 ; i < currentModel.length; i++) {
35
+ const entityKeys = Object.keys(currentModel[i].__entity);
36
+ // loop though all entity properties
37
+ for (const property of entityKeys) {
38
+ // cascade delete
39
+ if(currentModel[i].__entity[property].type === "hasOne" || currentModel[i].__entity[property].type === "hasMany"){
40
+ $that.cascadeDelete( currentModel[i][property]);
41
+ }
42
+ }
43
+ this._SQLEngine.delete(currentModel[i]);
44
+ }
45
+ }
46
+
47
+
48
+ }
49
+ }
50
+
51
+ module.exports = DeleteManager;
@@ -16,23 +16,26 @@
16
16
  :timestamp
17
17
 
18
18
  */
19
- // version 1.0.15
20
19
 
20
+ // version 1.0.16
21
21
  class EntityModel {
22
22
 
23
- constructor(){
23
+ constructor(name){
24
24
  this.obj = {
25
+ name: name,
25
26
  type: null,
26
27
  primary : null,
27
28
  default : null,
28
29
  virtual : null,
29
- belongsTo : null,
30
- get : null,
31
30
  foreignKey : null,
32
31
  maxLength : null,
33
- nullable : false, // no
34
- unique : null,
35
- autoIncrement : false
32
+ nullable : true, // no
33
+ unique : false,
34
+ auto : false,
35
+ cascadeOnDelete : true,
36
+ lazyLoading : true,
37
+ isNavigational : false
38
+
36
39
  }
37
40
  }
38
41
 
@@ -51,17 +54,33 @@ class EntityModel {
51
54
  return this;
52
55
  }
53
56
 
57
+ boolean(){
58
+ this.obj.type = "boolean";
59
+ return this;
60
+ }
61
+
54
62
  maxLength(amount){
55
63
  this.obj.maxLength = amount;
56
64
  return this;
57
65
  }
66
+
67
+ // will stop cascade delete which means it will stop not auto delete relationship
68
+ stopCascadeOnDelete(){
69
+ this.obj.cascadeOnDelete = false;
70
+ return this;
71
+ }
58
72
 
59
73
  // is this obj a primary key
60
74
  primary(){
61
75
  this.obj.primary = true;
62
76
  this.obj.nullable = false;
63
77
  this.obj.unique = true;
64
- this.obj.autoIncrement = true;
78
+ return this;
79
+ }
80
+
81
+ // allows ablity to get back primaryKey on insert automaticlly return on insert
82
+ auto(){
83
+ this.obj.auto = true;
65
84
  return this;
66
85
  }
67
86
 
@@ -71,10 +90,15 @@ class EntityModel {
71
90
  return this;
72
91
  }
73
92
 
74
- // get(func){
75
- // this.obj.get = func;
76
- // return this;
77
- // }
93
+ get(func){
94
+ this.obj.get = func;
95
+ return this;
96
+ }
97
+
98
+ set(func){
99
+ this.obj.set = func;
100
+ return this;
101
+ }
78
102
 
79
103
  unique(){
80
104
  this.obj.unique = true; // yes
@@ -82,11 +106,7 @@ class EntityModel {
82
106
 
83
107
  }
84
108
 
85
- autoIncrement(){
86
- this.obj.autoIncrement = true;
87
- return this;
88
- }
89
-
109
+ // this means that it can be an empty field
90
110
  nullable(){
91
111
  this.obj.nullable = true; // yes
92
112
  return this;
@@ -97,33 +117,77 @@ class EntityModel {
97
117
  return this;
98
118
  }
99
119
 
100
- virtual(tableName){
120
+ //allows you to stop lazy loading because lazy loading is added by default
121
+ lazyLoadingOff(){
122
+ this.obj.lazyLoading = false;
123
+ return this;
124
+ }
125
+
126
+ // allows you to add a virtual object that will skipped from being used as sql objects
127
+ virtual(){
101
128
  this.obj.virtual = true;
102
- if(tableName){
103
- this.obj.hasOne = tableName;
129
+ return this;
130
+ }
131
+
132
+ hasMany(foreignTable, foreignKey){
133
+ if(foreignKey === undefined){
134
+ foreignKey = `${this.obj.name.toLowerCase()}_id`;
104
135
  }
136
+ this.obj.type = "hasMany";
137
+ this.obj.foreignTable = foreignTable;
138
+ this.obj.foreignKey = foreignKey;
139
+ this.obj.isNavigational = true;
105
140
  return this;
106
141
  }
107
142
 
108
- hasMany(name){
109
- this.obj.hasMany = name;
143
+ hasOne(foreignTable, foreignKey){
144
+ if(foreignKey === undefined){
145
+ foreignKey = `${this.obj.name.toLowerCase()}_id`;
146
+ }
147
+ this.obj.type = "hasOne";
148
+ this.obj.foreignTable = foreignTable;
149
+ this.obj.foreignKey = foreignKey;
150
+ this.obj.isNavigational = true;
110
151
  return this;
111
152
  }
112
153
 
113
- hasOne(tableName){
114
- this.obj.hasOne = tableName;
154
+ // will do a inner join with foreignKey
155
+ //hasManyThrough("Tagging", "tag_id") ----- if foreignKey is not provided use the name of the object_id
156
+ hasManyThrough(foreignTable, foreignKey ){
157
+ if(foreignKey === undefined){
158
+ foreignKey = `${this.obj.name.toLowerCase()}_id`;
159
+ }
160
+ this.obj.type = "hasManyThrough";
161
+ this.obj.foreignTable = foreignTable;// if joinKey is undefined then use name of object.
162
+ this.obj.foreignKey = foreignKey; // Foreign Key table
163
+ this.obj.isNavigational = true;
115
164
  return this;
116
165
  }
117
-
118
- belongsTo(tableName){
119
- this.obj.foreignKey = tableName;
166
+
167
+ // will get info
168
+ belongsTo(foreignTable, foreignKey){
169
+
170
+ if(foreignKey === undefined){
171
+ foreignKey = `${foreignTable.toLowerCase()}_id`;
172
+ }
173
+ // will use table name to find forien key
174
+ this.obj.type = "belongsTo";
175
+ this.obj.foreignTable = foreignTable; // this is the table name of the current table if diffrent from the object name
176
+ this.obj.foreignKey = foreignKey; // this is the table name of the joining table
177
+ this.obj.nullable = false; // this means it cannot be null
120
178
  return this
121
179
  }
122
180
 
123
- hasForeignKey(tableName){
124
- this.obj.foreignKey = tableName;
125
- return this;
181
+ foreignKey(foreignKey){
182
+ this.obj.foreignKey = foreignKey;
183
+ this.obj.nullable = false;
184
+ return this
126
185
  }
127
186
 
187
+ foreignTable(foreignTable){
188
+ this.obj.foreignTable = foreignTable;
189
+ this.obj.nullable = false;
190
+ return this
191
+ }
128
192
  }
129
193
  module.exports = EntityModel;
@@ -3,7 +3,10 @@ var modelDB = require('./EntityModel');
3
3
  // creates new instance if entity model and calls inner functions to build out a valid entity
4
4
  class EntityModelBuilder {
5
5
 
6
- static init(model){
6
+ static create(model){
7
+ if(model.name === undefined){
8
+ throw "dbset model declaired incorrectly. Check you dbset models for code errors."
9
+ }
7
10
  var mod = new model(); //create new instance of Entity Model
8
11
  var obj = {};
9
12
  var methodNamesArray = Object.getOwnPropertyNames( mod.__proto__ );
@@ -14,7 +17,7 @@ class EntityModelBuilder {
14
17
  }
15
18
  // loop through all method names in the entity model
16
19
  for (var i = 0; i < methodNamesArray.length; i++) {
17
- let MDB = new modelDB(); // create a new instance of entity Model class
20
+ let MDB = new modelDB(model.name); // create a new instance of entity Model class
18
21
  mod[methodNamesArray[i]](MDB);
19
22
  this.cleanNull(MDB.obj); // remove objects that are null or undefined
20
23
  if(Object.keys(MDB.obj).length === 0){
@@ -28,37 +31,12 @@ class EntityModelBuilder {
28
31
 
29
32
  static cleanNull(obj) {
30
33
  for (var propName in obj) {
31
- if (obj[propName]) {
34
+ if (obj[propName] === null) {
32
35
  delete obj[propName];
33
36
  }
34
37
  }
35
38
  }
36
39
 
37
- static selectColumnQuery(objectLiteral){
38
- var arr = "";
39
- for(var keys = Object.keys(model), i = 0, end = keys.length; i < end; i++) {
40
- var key = keys[i], value = model[key];
41
- if(value.virtual === undefined){
42
- arr += key + ",";
43
- }
44
- };
45
- let cleaned = arr.substring(0, arr.length - 1);
46
- return cleaned;
47
- }
48
-
49
- // who calls this? What does this do?
50
- static callAllGets(data, model){
51
- console.log("callAllGets");
52
- for(var keys = Object.keys(model), i = 0, end = keys.length; i < end; i++) {
53
- var key = keys[i], value = model[key];
54
- if(value.get){
55
- data[key] = value.get(data);
56
- }
57
- };
58
-
59
- return data;
60
- }
61
-
62
40
  }
63
41
 
64
42
  module.exports = EntityModelBuilder;
@@ -1,43 +1,223 @@
1
+ var tools = require('../Tools');
1
2
  class EntityTrackerModel {
2
- constructor () {
3
- this.__ID = Math.floor((Math.random() * 100000) + 1);;
4
- this.__dirtyFields = [];
5
- this.__state = "track";
6
- this.__entity = null;
7
- this.__name = null;
8
- }
3
+
9
4
 
10
5
  // entity states https://docs.microsoft.com/en-us/dotnet/api/system.data.entitystate?view=netframework-4.7.2
11
6
 
12
7
  // start tracking model
13
- build(modelValue, currentEntity){
14
- this.__proto__ = {};
15
- const modelFields = Object.entries(modelValue); /// return array of objects
16
- var modelClass = this; // build entity with models
8
+ build(dataModel, currentEntity, context){
9
+ var $that = this;
10
+ var modelClass = this.buildObject(); // build entity with models
11
+ modelClass.__proto__ = {};
12
+ const modelFields = Object.entries(dataModel); /// return array of objects
17
13
  modelClass.__entity = currentEntity;
18
14
  modelClass.__name = currentEntity.__name;
19
-
20
- for (const [modelField, modelFieldValue] of modelFields) { // loop through database values
15
+ modelClass.__context = context;
16
+ this.buildRelationshipModels(modelClass, currentEntity, dataModel);
17
+
18
+ // loop through data model fields
19
+ for (const [modelField, modelFieldValue] of modelFields) {
20
+
21
21
  // set the value dynamiclly
22
- if(currentEntity[modelField]){ // current entity has a value then add
23
- modelClass["_" + modelField] = modelFieldValue;
22
+ if(!$that._isRelationship(currentEntity[modelField])){
23
+ // current entity has a value then add
24
+ modelClass["__proto__"]["_" + modelField] = modelFieldValue;
24
25
 
25
26
  // Setter
26
- this.__proto__.__defineSetter__(modelField, function(value){
27
+ modelClass.__defineSetter__(modelField, function(value){
27
28
  modelClass.__state = "modified";
28
29
  modelClass.__dirtyFields.push(modelField);
29
- // Then it will add name to dirty fields
30
- this["_" + modelField] = value;
30
+ if(typeof currentEntity[modelField].set === "function"){
31
+ this["__proto__"]["_" + modelField] = currentEntity[modelField].set(value);
32
+ }else{
33
+ // Then it will add name to dirty fields
34
+ this["__proto__"]["_" + modelField] = value;
35
+ }
31
36
  });
32
37
 
33
38
  // Getter
34
- this.__proto__.__defineGetter__(modelField, function(){
35
- return this["_" + modelField];
39
+ modelClass.__defineGetter__(modelField, function(){
40
+ if(typeof currentEntity[modelField].get === "function"){
41
+ return currentEntity[modelField].get(this["__proto__"]["_" + modelField]);
42
+ }else{
43
+ return this["__proto__"]["_" + modelField];
44
+ }
45
+
36
46
  });
37
47
  }
38
48
  }
49
+
50
+
39
51
  return modelClass;
40
52
  }
53
+
54
+ buildObject(){
55
+ return {
56
+ __ID : Math.floor((Math.random() * 100000) + 1),
57
+ __dirtyFields : [],
58
+ __state : "track",
59
+ __entity : null,
60
+ __context : null,
61
+ __name : null
62
+ }
63
+ }
64
+
65
+ _isRelationship(entity){
66
+ if(entity){
67
+ if(entity.type === "hasOne" || entity.type === "hasMany" || entity.type === "belongsTo" || entity.type === "hasManyThrough"){
68
+ return true;
69
+ }
70
+ else{
71
+ return false;
72
+ }
73
+ }else{
74
+ return false;
75
+ }
76
+ }
77
+
78
+ buildRelationshipModels(modelClass, currentEntity, currentModel){
79
+ var $that = this;
80
+ // loop though current entity and add only relationship models to this list
81
+ const entityFields = Object.entries(currentEntity);
82
+ for (const [entityField, entityFieldValue] of entityFields) { // loop through entity values
83
+
84
+ if($that._isRelationship(currentEntity[entityField])){
85
+
86
+ // Setter
87
+ modelClass.__defineSetter__(entityField, function(value){
88
+ this["__proto__"]["_" + entityField] = value;
89
+ });
90
+
91
+ // Getter
92
+ modelClass.__defineGetter__(entityField, function(){
93
+
94
+ var ent = tools.findEntity(entityField, this.__context);
95
+ if(!ent){
96
+ var parentEntity = tools.findEntity(this.__name, this.__context);
97
+ if(parentEntity){
98
+ ent = tools.findEntity(parentEntity.__entity[entityField].foreignKey, this.__context);
99
+ if(!ent){
100
+ return `Error - Entity ${parentEntity.__entity[entityField].foreignTable} not found. Please check your context for proper name.`
101
+ }
102
+ }
103
+ else{
104
+ return `Error - Entity ${parentEntity} not found. Please check your context for proper name.`
105
+ }
106
+ }
107
+
108
+
109
+ if(currentEntity[entityField].type === "belongsTo"){
110
+ if(currentEntity[entityField].lazyLoading){
111
+ var priKey = tools.getPrimaryKeyObject(this.__entity);
112
+ var currentValue = this.__proto__[`_${entityField}`];
113
+ if(currentValue){
114
+ // CHECK to see if you got the info already
115
+ if(typeof currentValue === 'object'){
116
+ currentValue = currentValue[priKey];
117
+ }
118
+ }
119
+ else{
120
+ var idValue = currentEntity[entityField].foreignTable;
121
+ currentValue = this.__proto__[`_${idValue}`];
122
+ }
123
+
124
+ //var modelValue = ent.raw(`select * from ${ent.__entity.__name} where ${priKey} = ${ currentValue }`).single();
125
+ var modelValue = ent.where(`r => r. ${priKey} == ${ currentValue }`)
126
+ this[entityField] = modelValue;
127
+ }
128
+ else{
129
+ return this["__proto__"]["_" + entityField];
130
+ }
131
+ }
132
+ else{
133
+ // user.tags = gets all tags related to user
134
+ // tag.users = get all users related to tags
135
+ if(currentEntity[entityField].lazyLoading){
136
+ var priKey = tools.getPrimaryKeyObject(this.__entity);
137
+ var entityName = currentEntity[entityField].foreignTable === undefined ? entityField : currentEntity[entityField].foreignTable;
138
+ var tableName = "";
139
+ if(entityName){
140
+ switch(currentEntity[entityField].type){
141
+ // TODO: move the SQL generation part to the SQL builder so that we can later on use many diffrent types of SQL databases.
142
+ case "hasManyThrough" :
143
+ try{
144
+ var joiningEntity = this.__context[tools.capitalize(entityName)];
145
+ var entityFieldJoinName = currentEntity[entityField].foreignTable === undefined? entityField : currentEntity[entityField].foreignTable;
146
+ var thirdEntity = this.__context[tools.capitalize(entityFieldJoinName)];
147
+ var firstJoiningID = joiningEntity.__entity[this.__entity.__name].foreignTable;
148
+ var secondJoiningID = joiningEntity.__entity[entityField].foreignTable;
149
+ if(firstJoiningID && secondJoiningID )
150
+ {
151
+ var modelValue = ent.include(`p => p.${entityFieldJoinName}.select(j => j.${joiningEntity.__entity[this.__entity.__name].foreignKey})`).include(`p =>p.${this.__entity.__name}`).where(`r =>r.${this.__entity.__name}.${priKey} = ${this[priKey]}`).toList();
152
+ // var modelQuery = `select ${selectParameter} from ${this.__entity.__name} INNER JOIN ${entityName} ON ${this.__entity.__name}.${priKey} = ${entityName}.${firstJoiningID} INNER JOIN ${entityField} ON ${entityField}.${joinTablePriKey} = ${entityName}.${secondJoiningID} WHERE ${this.__entity.__name}.${priKey} = ${ this[priKey]}`;
153
+ // var modelValue = ent.raw(modelQuery).toList();
154
+ this[entityField] = modelValue;
155
+ }
156
+ else{
157
+ return "Joining table must declaire joining table names"
158
+ }
159
+ }
160
+ catch(error){
161
+ return error;
162
+ }
163
+ /*
164
+ select * from User
165
+ INNER JOIN Tagging ON User.id = Tagging.user_id
166
+ INNER JOIN Tag ON Tag.id = Tagging.tag_id
167
+ WHERE Tagging.user_id = 13
168
+ */
169
+ break;
170
+ case "hasOne" :
171
+ if(ent.__entity[this.__entity.__name]){
172
+ tableName = ent.__entity[this.__entity.__name].foreignKey;
173
+ }
174
+ else{
175
+ return `Error - Entity ${ent.__entity.__name} has no property named ${this.__entity.__name}`;
176
+ }
177
+
178
+ //var jj = ent.raw(`select * from ${entityName} where ${tableName} = ${ this[priKey] }`).single();
179
+ var modelValue = ent.where(`r => r.${tableName} == ${this[priKey]}`).single();
180
+ this[entityField] = modelValue;
181
+ break;
182
+ case "hasMany" :
183
+ if(ent.__entity[this.__entity.__name]){
184
+ tableName = ent.__entity[this.__entity.__name].foreignKey;
185
+ }
186
+ else{
187
+ return `Error - Entity ${ent.__entity.__name} has no property named ${this.__entity.__name}`;
188
+ }
189
+ //var modelValue = ent.raw(`select * from ${entityName} where ${tableName} = ${ this[priKey] }`).toList();
190
+ var modelValue = ent.where(`r => r.${tableName} == ${this[priKey]}`).toList();
191
+ this[entityField] = modelValue;
192
+ break;
193
+ }
194
+ }
195
+ else{
196
+ return "Entity name must be defined"
197
+ }
198
+ }
199
+ else{
200
+ return this["__proto__"]["_" + entityField];
201
+ }
202
+ }
203
+
204
+
205
+ return this["__proto__"]["_" + entityField];
206
+ //return console.log("make db call to get value", entityField);
207
+ });
208
+
209
+ if(currentEntity[entityField].type === "belongsTo"){
210
+ // check if entity has a value if so then return that value
211
+ if(currentModel[entityField]){
212
+ modelClass[entityField] = currentModel[entityField];
213
+ }
214
+ }
215
+
216
+ }
217
+
218
+ }
219
+ }
220
+
41
221
  }
42
222
 
43
223
  module.exports = EntityTrackerModel