masterrecord 0.0.23 → 0.0.25

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.
@@ -1,43 +1,223 @@
1
- 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
- }
9
-
10
- // entity states https://docs.microsoft.com/en-us/dotnet/api/system.data.entitystate?view=netframework-4.7.2
11
-
12
- // 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
17
- modelClass.__entity = currentEntity;
18
- modelClass.__name = currentEntity.__name;
19
-
20
- for (const [modelField, modelFieldValue] of modelFields) { // loop through database values
21
- // set the value dynamiclly
22
- if(currentEntity[modelField]){ // current entity has a value then add
23
- modelClass["_" + modelField] = modelFieldValue;
24
-
25
- // Setter
26
- this.__proto__.__defineSetter__(modelField, function(value){
27
- modelClass.__state = "modified";
28
- modelClass.__dirtyFields.push(modelField);
29
- // Then it will add name to dirty fields
30
- this["_" + modelField] = value;
31
- });
32
-
33
- // Getter
34
- this.__proto__.__defineGetter__(modelField, function(){
35
- return this["_" + modelField];
36
- });
37
- }
38
- }
39
- return modelClass;
40
- }
41
- }
42
-
1
+ var tools = require('../Tools');
2
+ class EntityTrackerModel {
3
+
4
+
5
+ // entity states https://docs.microsoft.com/en-us/dotnet/api/system.data.entitystate?view=netframework-4.7.2
6
+
7
+ // start tracking model
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
13
+ modelClass.__entity = currentEntity;
14
+ modelClass.__name = currentEntity.__name;
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
+ // set the value dynamiclly
22
+ if(!$that._isRelationship(currentEntity[modelField])){
23
+ // current entity has a value then add
24
+ modelClass["__proto__"]["_" + modelField] = modelFieldValue;
25
+
26
+ // Setter
27
+ modelClass.__defineSetter__(modelField, function(value){
28
+ modelClass.__state = "modified";
29
+ modelClass.__dirtyFields.push(modelField);
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
+ }
36
+ });
37
+
38
+ // Getter
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
+
46
+ });
47
+ }
48
+ }
49
+
50
+
51
+ return modelClass;
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
+
221
+ }
222
+
43
223
  module.exports = EntityTrackerModel
@@ -0,0 +1,138 @@
1
+
2
+ var tools = require('./Tools');
3
+ class InsertManager {
4
+ // TODO: WE are using the relationshipTable and the object name stick to one so that hasMany doesnt have to give a name
5
+ constructor(sqlEngine, errorModel, allEntities ){
6
+ this._SQLEngine = sqlEngine;
7
+ this._errorModel = errorModel;
8
+ this._allEntities = allEntities;
9
+ }
10
+
11
+ init(currentModel){
12
+ this.runQueries(currentModel);
13
+ }
14
+
15
+ runQueries(currentModel){
16
+ var $that = this;
17
+ var cleanCurrentModel = tools.removePrimarykeyandVirtual(currentModel, currentModel.__entity);
18
+ this.validateEntity(cleanCurrentModel, currentModel, currentModel.__entity);
19
+ if(this._errorModel.isValid){
20
+
21
+ var modelEntity = currentModel.__entity;
22
+ // TODO: if you try to add belongs to you must have a tag added first. if you dont throw error
23
+ currentModel = this.belongsToInsert(currentModel, modelEntity);
24
+ var SQL = this._SQLEngine.insert(currentModel);
25
+ var primaryKey = tools.getPrimaryKeyObject(currentModel.__entity);
26
+ // return all fields that have auto and dont have a value to the current model on insert
27
+ if(currentModel.__entity[primaryKey].auto === true){
28
+ var getQueryModel = this._SQLEngine.get(`select * from ${currentModel.__entity.__name} where ${primaryKey} = ${ SQL.id }`);
29
+ currentModel[primaryKey] = getQueryModel[primaryKey];
30
+ }
31
+
32
+ const modelKeys = Object.keys(currentModel);
33
+ // loop through model properties
34
+ for (const property of modelKeys) {
35
+ var propertyModel = currentModel[property];
36
+ var entityProperty = modelEntity[property] ? modelEntity[property] : {};
37
+ if(entityProperty.type === "hasOne"){
38
+ // make sure property model is an object not a primary data type like number or string
39
+ if(typeof(propertyModel) === "object"){
40
+ // check if model has its own entity
41
+ if(modelEntity){
42
+ propertyModel.__entity = tools.getEntity(property, $that._allEntities);
43
+ propertyModel[currentModel.__entity.__name] = SQL.id;
44
+ $that.runQueries(propertyModel);
45
+ }
46
+ else{
47
+ throw `Relationship "${entityProperty.name}" could not be found please check if object has correct spelling or if it has been added to the context class`
48
+ }
49
+ }
50
+ }
51
+
52
+ if(entityProperty.type === "hasMany"){
53
+ if(Array.isArray(propertyModel)){
54
+ const propertyKeys = Object.keys(propertyModel);
55
+ for (const propertykey of propertyKeys) {
56
+ if(propertyModel[propertykey]){
57
+ propertyModel[propertykey].__entity = tools.getEntity(property, $that._allEntities);
58
+ propertyModel[propertykey][currentModel.__entity.__name] = SQL.id;
59
+ $that.runQueries(propertyModel[propertykey]);
60
+ }
61
+ }
62
+ }
63
+ else{
64
+ throw `Relationship "${entityProperty.name}" must be an array`;
65
+ }
66
+ }
67
+
68
+ }
69
+ }
70
+ else{
71
+ var name = currentModel.__entity.__name;
72
+ console.log(`entity ${name} not valid`);
73
+ }
74
+ }
75
+
76
+ // will insert belongs to row first and return the id so that next call can be make correctly
77
+ belongsToInsert(currentModel, modelEntity){
78
+ var $that = this;
79
+ for(var entity in modelEntity) {
80
+ if(modelEntity[entity].type === "belongsTo"){
81
+ var foreignKey = modelEntity[entity].foreignKey === undefined ? modelEntity[entity].name : modelEntity[entity].foreignKey;
82
+ var newPropertyModel = currentModel[foreignKey];
83
+ // check if model is a value because if so then skip we dont need to make an ajax call
84
+ if(typeof newPropertyModel === 'object'){
85
+ newPropertyModel.__entity = tools.getEntity(entity, $that._allEntities);
86
+ var propertyCleanCurrentModel = tools.removePrimarykeyandVirtual(newPropertyModel, newPropertyModel.__entity);
87
+ this.validateEntity(propertyCleanCurrentModel, newPropertyModel, newPropertyModel.__entity);
88
+ var propertySQL = this._SQLEngine.insert(newPropertyModel);
89
+ currentModel[foreignKey] = propertySQL.id;
90
+ }
91
+ }
92
+ }
93
+ // todo:
94
+ // loop through all modelEntity and find all the belongs to
95
+ // if belongs to is true then make sql call to insert
96
+ // update the currentModel.
97
+ return currentModel;
98
+ }
99
+ // validate entity for nullable fields
100
+ validateEntity(currentModel, currentRealModel, entityModel){
101
+ for(var entity in entityModel) {
102
+ var currentEntity = entityModel[entity];
103
+ if (entityModel.hasOwnProperty(entity)) {
104
+ // check if there is a default value
105
+ if(currentEntity.default){
106
+ if(!currentRealModel[entity]){
107
+ // if its empty add the default value
108
+ currentRealModel[entity] = currentEntity.default;
109
+ }
110
+ }
111
+
112
+ // SKIP belongs too
113
+ if(currentEntity.type !== "belongsTo"){
114
+ // primary is always null in an insert so validation insert must be null
115
+ if(currentEntity.nullable === false && !currentEntity.primary){
116
+ // if it doesnt have a get method then call error
117
+ if(currentEntity.get === undefined){
118
+ if(currentModel[entity] === undefined || currentModel[entity] === null || currentModel[entity] === "" ){
119
+ this._errorModel.isValid = false;
120
+ var errorMessage = `Entity ${currentModel.__entity.__name} column ${entity} is a required Field`;
121
+ this._errorModel.errors.push(errorMessage);
122
+ throw errorMessage;
123
+ }
124
+ }
125
+ else{
126
+ currentRealModel[entity] = currentEntity.get(currentModel[entity]);
127
+ }
128
+ }
129
+ }
130
+ }
131
+
132
+ }
133
+ }
134
+
135
+ }
136
+
137
+
138
+ module.exports = InsertManager;