masterrecord 0.3.20 → 0.3.22

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.
@@ -164,7 +164,7 @@ class queryMethods{
164
164
  // ------------------------------- FUNCTIONS THAT MAKE THE SQL CALL START FROM HERE ON -----------------------------------------------------
165
165
  // ---------------------------------------------------------------------------------------------------------------------------------------
166
166
 
167
- count(query, ...args){
167
+ async count(query, ...args){
168
168
  if(query){
169
169
  var str = query.toString();
170
170
  str = this.__validateAndCollectParameters(str, args, 'count');
@@ -173,7 +173,7 @@ class queryMethods{
173
173
 
174
174
  if(this.__context.isSQLite){
175
175
  // trying to match string select and relace with select Count(*);
176
- var entityValue = this.__context._SQLEngine.getCount(this.__queryObject, this.__entity, this.__context);
176
+ var entityValue = await this.__context._SQLEngine.getCount(this.__queryObject, this.__entity, this.__context);
177
177
  var val = entityValue[Object.keys(entityValue)[0]];
178
178
  this.__reset();
179
179
  return val;
@@ -181,7 +181,7 @@ class queryMethods{
181
181
 
182
182
  if(this.__context.isMySQL){
183
183
  // trying to match string select and relace with select Count(*);
184
- var entityValue = this.__context._SQLEngine.getCount(this.__queryObject, this.__entity, this.__context);
184
+ var entityValue = await this.__context._SQLEngine.getCount(this.__queryObject, this.__entity, this.__context);
185
185
  var val = entityValue[Object.keys(entityValue)[0]];
186
186
  this.__reset();
187
187
  return val;
@@ -309,7 +309,7 @@ class queryMethods{
309
309
  }
310
310
 
311
311
  // Convenience method: Find record by primary key ID
312
- findById(id){
312
+ async findById(id){
313
313
  // Find the primary key field in the entity
314
314
  let primaryKeyField = null;
315
315
  for (const fieldName in this.__entity) {
@@ -329,10 +329,10 @@ class queryMethods{
329
329
  const whereClause = `${entityParam} => ${entityParam}.${primaryKeyField} == $$`;
330
330
 
331
331
  // Chain where() and single()
332
- return this.where(whereClause, id).single();
332
+ return await this.where(whereClause, id).single();
333
333
  }
334
334
 
335
- single(){
335
+ async single(){
336
336
  // If no clauses were used before single(), seed defaults so SQL is valid
337
337
  if(this.__queryObject.script.entityMap.length === 0){
338
338
  this.__queryObject.skipClause(this.__entity.__name);
@@ -357,12 +357,12 @@ class queryMethods{
357
357
  // Cache miss - execute query
358
358
  var result = null;
359
359
  if(this.__context.isSQLite){
360
- var entityValue = this.__context._SQLEngine.get(this.__queryObject.script, this.__entity, this.__context);
360
+ var entityValue = await this.__context._SQLEngine.get(this.__queryObject.script, this.__entity, this.__context);
361
361
  result = this.__singleEntityBuilder(entityValue);
362
362
  }
363
363
 
364
364
  if(this.__context.isMySQL){
365
- var entityValue = this.__context._SQLEngine.get(this.__queryObject.script, this.__entity, this.__context);
365
+ var entityValue = await this.__context._SQLEngine.get(this.__queryObject.script, this.__entity, this.__context);
366
366
  result = this.__singleEntityBuilder(entityValue[0]);
367
367
  }
368
368
 
@@ -375,7 +375,7 @@ class queryMethods{
375
375
  return result;
376
376
  }
377
377
 
378
- toList(){
378
+ async toList(){
379
379
  if(this.__queryObject.script.entityMap.length === 0){
380
380
  this.__queryObject.skipClause( this.__entity.__name);
381
381
  if(!this.__queryObject.script.take || this.__queryObject.script.take === 0){
@@ -401,12 +401,12 @@ class queryMethods{
401
401
  // Cache miss - execute query
402
402
  var result = [];
403
403
  if(this.__context.isSQLite){
404
- var entityValue = this.__context._SQLEngine.all(this.__queryObject.script, this.__entity, this.__context);
404
+ var entityValue = await this.__context._SQLEngine.all(this.__queryObject.script, this.__entity, this.__context);
405
405
  result = this.__multipleEntityBuilder(entityValue);
406
406
  }
407
407
 
408
408
  if(this.__context.isMySQL){
409
- var entityValue = this.__context._SQLEngine.all(this.__queryObject.script, this.__entity, this.__context);
409
+ var entityValue = await this.__context._SQLEngine.all(this.__queryObject.script, this.__entity, this.__context);
410
410
  result = this.__multipleEntityBuilder(entityValue);
411
411
  }
412
412
 
package/context.js CHANGED
@@ -452,7 +452,35 @@ class context {
452
452
  const rel = files[0];
453
453
  // Ensure absolute path for require()
454
454
  const abs = path.isAbsolute(rel) ? rel : path.resolve(currentRoot, rel);
455
- return { file: abs, rootFolder: currentRoot };
455
+
456
+ // Find actual project root by looking for package.json or .git
457
+ // This prevents duplicate paths like "app/models/components/workforce/db/"
458
+ let projectRoot = path.dirname(abs);
459
+ let searchDir = projectRoot;
460
+ let foundProjectRoot = false;
461
+
462
+ // Walk up the directory tree to find package.json or .git
463
+ for (let j = 0; j < MAX_CONFIG_SEARCH_HOPS; j++) {
464
+ const hasPackageJson = fs.existsSync(path.join(searchDir, 'package.json'));
465
+ const hasGit = fs.existsSync(path.join(searchDir, '.git'));
466
+
467
+ if (hasPackageJson || hasGit) {
468
+ projectRoot = searchDir;
469
+ foundProjectRoot = true;
470
+ break;
471
+ }
472
+
473
+ const parent = path.dirname(searchDir);
474
+ if (parent === searchDir) break; // Reached filesystem root
475
+ searchDir = parent;
476
+ }
477
+
478
+ // Fallback to currentRoot if no project markers found
479
+ if (!foundProjectRoot) {
480
+ projectRoot = currentRoot;
481
+ }
482
+
483
+ return { file: abs, rootFolder: projectRoot };
456
484
  }
457
485
 
458
486
  // Move to parent directory
@@ -1450,7 +1478,7 @@ class context {
1450
1478
  }
1451
1479
 
1452
1480
  // Load entity
1453
- const entity = EntityClass.findById(primaryKey);
1481
+ const entity = await EntityClass.findById(primaryKey);
1454
1482
  if (!entity) {
1455
1483
  throw new EntityValidationError(
1456
1484
  `${entityName} with id ${primaryKey} not found`,
package/insertManager.js CHANGED
@@ -115,15 +115,15 @@ class InsertManager {
115
115
  const entityProperty = modelEntity[property] ? modelEntity[property] : {};
116
116
 
117
117
  if (entityProperty.type === RELATIONSHIP_TYPES.HAS_ONE) {
118
- this._processHasOneRelationship(propertyModel, entityProperty, property, currentModel, SQL);
118
+ await this._processHasOneRelationship(propertyModel, entityProperty, property, currentModel, SQL);
119
119
  }
120
120
 
121
121
  if (entityProperty.type === RELATIONSHIP_TYPES.HAS_MANY) {
122
- this._processArrayRelationship(propertyModel, entityProperty, property, currentModel, SQL, RELATIONSHIP_TYPES.HAS_MANY);
122
+ await this._processArrayRelationship(propertyModel, entityProperty, property, currentModel, SQL, RELATIONSHIP_TYPES.HAS_MANY);
123
123
  }
124
124
 
125
125
  if (entityProperty.type === RELATIONSHIP_TYPES.HAS_MANY_THROUGH) {
126
- this._processArrayRelationship(propertyModel, entityProperty, property, currentModel, SQL, RELATIONSHIP_TYPES.HAS_MANY_THROUGH);
126
+ await this._processArrayRelationship(propertyModel, entityProperty, property, currentModel, SQL, RELATIONSHIP_TYPES.HAS_MANY_THROUGH);
127
127
  }
128
128
  }
129
129
  } else {
@@ -147,7 +147,7 @@ class InsertManager {
147
147
  * @param {object} SQL - SQL result from parent insert
148
148
  * @throws {RelationshipError} If relationship entity is not found
149
149
  */
150
- _processHasOneRelationship(propertyModel, entityProperty, property, currentModel, SQL) {
150
+ async _processHasOneRelationship(propertyModel, entityProperty, property, currentModel, SQL) {
151
151
  // only insert child if user provided a concrete object with data
152
152
  if (propertyModel && typeof propertyModel === 'object') {
153
153
  // check if model has its own entity
@@ -169,7 +169,7 @@ class InsertManager {
169
169
 
170
170
  propertyModel.__entity = tools.getEntity(property, this._allEntities);
171
171
  propertyModel[currentModel.__entity.__name] = SQL.id;
172
- this.runQueries(propertyModel);
172
+ await this.runQueries(propertyModel);
173
173
 
174
174
  // Hydrate child back as a tracked instance so subsequent property sets are tracked
175
175
  try {
@@ -187,7 +187,7 @@ class InsertManager {
187
187
 
188
188
  const ctxSetName = tools.capitalizeFirstLetter(property);
189
189
  if (currentModel.__context && currentModel.__context[ctxSetName]) {
190
- const trackedChild = currentModel.__context[ctxSetName]
190
+ const trackedChild = await currentModel.__context[ctxSetName]
191
191
  .where(`r => r.${childPk} == $$`, childId)
192
192
  .single();
193
193
  if (trackedChild) {
@@ -218,7 +218,7 @@ class InsertManager {
218
218
  * @param {string} relationshipType - 'hasMany' or 'hasManyThrough'
219
219
  * @throws {RelationshipError} If validation fails or entity not resolved
220
220
  */
221
- _processArrayRelationship(propertyModel, entityProperty, property, currentModel, SQL, relationshipType) {
221
+ async _processArrayRelationship(propertyModel, entityProperty, property, currentModel, SQL, relationshipType) {
222
222
  // skip when not provided; only enforce array type if user supplied a value
223
223
  if (propertyModel === undefined || propertyModel === null) {
224
224
  return;
@@ -263,7 +263,7 @@ class InsertManager {
263
263
 
264
264
  propertyModel[propertykey].__entity = resolved;
265
265
  propertyModel[propertykey][currentModel.__entity.__name] = SQL.id;
266
- this.runQueries(propertyModel[propertykey]);
266
+ await this.runQueries(propertyModel[propertykey]);
267
267
  }
268
268
  }
269
269
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "masterrecord",
3
- "version": "0.3.20",
3
+ "version": "0.3.22",
4
4
  "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 ",
5
5
  "main": "MasterRecord.js",
6
6
  "bin": {