| 
					
				 | 
			
			
				@@ -3,13 +3,13 @@ import config from "config"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { Db, MongoClient, ObjectId } from "mongodb"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import hash from "object-hash"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { createClient, RedisClientType } from "redis"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { Document } from "src/types/Document"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import JobContext from "../JobContext"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import BaseModule from "../BaseModule"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import ModuleManager from "../ModuleManager"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import Schema, { Types } from "../Schema"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { UniqueMethods } from "../types/Modules"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { Collections } from "../types/Collections"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Document } from "../types/Document"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { UniqueMethods } from "../types/Modules"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 interface ProjectionObject { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	[property: string]: boolean | string[] | ProjectionObject; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -38,10 +38,6 @@ export default class DataModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	public constructor(moduleManager: ModuleManager) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		super(moduleManager, "data"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		const a = this.normalizeProjection({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			test123: true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	/** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -181,7 +177,7 @@ export default class DataModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 * Takes a raw projection and turns it into a projection we can easily use 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 * @param projection The raw projection 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 * @param projection - The raw projection 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 * @returns Normalized projection 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	private normalizeProjection(projection: Projection): NormalizedProjection { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -307,7 +303,7 @@ export default class DataModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		allowedRestricted: any 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		// The mongo projection object we're going to build 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		const mongoProjection = {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		const mongoProjection: ProjectionObject = {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		// This will be false if we let Mongo return any restricted properties 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		let canCache = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -344,6 +340,7 @@ export default class DataModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					key 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (!value.schema) throw new Error("Schema is not defined"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				// Parse projection for the current value, so one level deeper 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				const parsedProjection = await this.parseFindProjection( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					deeperProjection, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -551,7 +548,7 @@ export default class DataModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if (schemaType === Types.ObjectId) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			// Cast the value as an ObjectId and let Mongoose handle the rest 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			const castedValue = ObjectId(value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			const castedValue = new ObjectId(value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			// Any additional validation comes here 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			return castedValue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -675,9 +672,9 @@ export default class DataModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 						if ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 							schema[currentKey].type !== Types.Schema && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 							(schema[currentKey].type !== Types.Array || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-								(schema[currentKey].item.type !== 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								(schema[currentKey].item!.type !== 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 									Types.Schema && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-									schema[currentKey].item.type !== 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+									schema[currentKey].item!.type !== 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 										Types.Array)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 						) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 							throw new Error( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1068,7 +1065,7 @@ export default class DataModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			filter, // Similar to MongoDB filter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			projection, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			allowedRestricted, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			limit = 0, // TODO have limit off by default? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			limit = 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			page = 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			useCache = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		}: { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1091,10 +1088,22 @@ export default class DataModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			let normalizedProjection: NormalizedProjection; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			let mongoFilter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			let mongoProjection; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			let mongoProjection: ProjectionObject; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			async.waterfall( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				[ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// Verify page and limit parameters 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						if (page < 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							throw new Error("Page must be at least 1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						if (limit < 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							throw new Error("Limit must be at least 1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						if (limit > 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							throw new Error( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								"Limit must not be greater than 100" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					// Verify whether the collection exists, and get the schema 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 						if (!collection) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1181,6 +1190,16 @@ export default class DataModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 						// TODO, add mongo projection. Make sure to keep in mind caching with queryHash. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						const totalCount = await this.collections?.[ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							collection 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						].collection.countDocuments({ $expr: mongoFilter }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						if (totalCount === 0) return []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						const lastPage = Math.ceil(totalCount / limit); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						if (lastPage < page) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							throw new Error( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								`The last page available is ${lastPage}` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 						// Create the Mongo cursor and then return the promise that gets the array of documents 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 						return this.collections?.[collection].collection 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 							.find(mongoFilter, mongoProjection) 
			 |