Przeglądaj źródła

refactor: started fixing some TypeScript errors in DataModule

Kristian Vos 2 lat temu
rodzic
commit
d5950cb095
1 zmienionych plików z 57 dodań i 82 usunięć
  1. 57 82
      backend/src/modules/DataModule.ts

+ 57 - 82
backend/src/modules/DataModule.ts

@@ -1,9 +1,9 @@
-// @ts-nocheck
 import async from "async";
 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";
@@ -11,6 +11,17 @@ import Schema, { Types } from "../Schema";
 import { UniqueMethods } from "../types/Modules";
 import { Collections } from "../types/Collections";
 
+interface ProjectionObject {
+	[property: string]: boolean | string[] | ProjectionObject;
+}
+
+type Projection = null | undefined | string[] | ProjectionObject;
+
+type NormalizedProjection = {
+	projection: [string, boolean][];
+	mode: "includeAllBut" | "excludeAllBut";
+};
+
 export default class DataModule extends BaseModule {
 	private collections?: Collections;
 
@@ -27,6 +38,10 @@ export default class DataModule extends BaseModule {
 	 */
 	public constructor(moduleManager: ModuleManager) {
 		super(moduleManager, "data");
+
+		const a = this.normalizeProjection({
+			test123: true
+		});
 	}
 
 	/**
@@ -115,63 +130,6 @@ export default class DataModule extends BaseModule {
 		});
 	}
 
-	/**
-	 *
-	 * @param schema Our own schema format
-	 * @returns A Mongoose-compatible schema format
-	 */
-	private convertSchemaToMongooseSchema(schema: any) {
-		// Convert basic types from our own schema types to Mongoose schema types
-		const typeToMongooseType = (type: Types) => {
-			switch (type) {
-				case Types.String:
-					return String;
-				case Types.Number:
-					return Number;
-				case Types.Date:
-					return Date;
-				case Types.Boolean:
-					return Boolean;
-				case Types.ObjectId:
-					return MongooseTypes.ObjectId;
-				default:
-					return null;
-			}
-		};
-
-		const schemaEntries = Object.entries(schema);
-		const mongooseSchemaEntries = schemaEntries.map(([key, value]) => {
-			let mongooseEntry = {};
-
-			// Handle arrays
-			if (value.type === Types.Array) {
-				// Handle schemas in arrays
-				if (value.item.type === Types.Schema)
-					mongooseEntry = [
-						this.convertSchemaToMongooseSchema(value.item.schema)
-					];
-				// We don't support nested arrays
-				else if (value.item.type === Types.Array)
-					throw new Error("Nested arrays are not supported.");
-				// Handle regular types in array
-				else mongooseEntry.type = [typeToMongooseType(value.item.type)];
-			}
-			// Handle schemas
-			else if (value.type === Types.Schema)
-				mongooseEntry = this.convertSchemaToMongooseSchema(
-					value.schema
-				);
-			// Handle regular types
-			else mongooseEntry.type = typeToMongooseType(value.type);
-
-			return [key, mongooseEntry];
-		});
-
-		const mongooseSchema = Object.fromEntries(mongooseSchemaEntries);
-
-		return mongooseSchema;
-	}
-
 	/**
 	 * loadColllection - Import and load collection schema
 	 *
@@ -180,13 +138,16 @@ export default class DataModule extends BaseModule {
 	 */
 	private loadCollection<T extends keyof Collections>(
 		collectionName: T
-	): Promise<Collections[T]> {
+	): Promise<{
+		schema: Collections[T]["schema"];
+		collection: Collections[T]["collection"];
+	}> {
 		return new Promise(resolve => {
 			import(`../collections/${collectionName.toString()}`).then(
 				({ default: schema }: { default: Schema }) => {
 					resolve({
 						schema,
-						collection: this.mongoDb?.collection(
+						collection: this.mongoDb!.collection(
 							collectionName.toString()
 						)
 					});
@@ -223,7 +184,7 @@ export default class DataModule extends BaseModule {
 	 * @param projection The raw projection
 	 * @returns Normalized projection
 	 */
-	private normalizeProjection(projection: any) {
+	private normalizeProjection(projection: Projection): NormalizedProjection {
 		let initialProjection = projection;
 		if (
 			!(projection && typeof initialProjection === "object") &&
@@ -251,7 +212,9 @@ export default class DataModule extends BaseModule {
 			// Non-nested paths don't need to be checked, they're covered by the earlier path collision checking
 			if (key.indexOf(".") !== -1) {
 				// Recursively check for each layer of a key whether that key exists already, and if it does, throw a path collision error
-				const recursivelyCheckForPathCollision = keyToCheck => {
+				const recursivelyCheckForPathCollision = (
+					keyToCheck: string
+				) => {
 					// Remove the last ".prop" from the key we want to check, to check if that has any collisions
 					const subKey = keyToCheck.substring(
 						0,
@@ -279,7 +242,7 @@ export default class DataModule extends BaseModule {
 		);
 
 		// By default, include everything except keys whose value is false
-		let mode = "includeAllBut";
+		let mode: "includeAllBut" | "excludeAllBut" = "includeAllBut";
 
 		// If in the projection we have any keys whose value is true (with the exception of _id), switch to excluding all but keys we explicitly set to true in the projection
 		if (anyNonIdTrues) mode = "excludeAllBut";
@@ -293,8 +256,13 @@ export default class DataModule extends BaseModule {
 	 * @param projection
 	 * @returns
 	 */
-	private flattenProjection(projection: any) {
-		let flattenedProjection = [];
+	private flattenProjection(projection: Projection): [string, boolean][] {
+		let flattenedProjection: [
+			string,
+			boolean | string[] | ProjectionObject
+		][] = [];
+
+		if (!projection) throw new Error("Projection can't be null");
 
 		// Turn object/array into a key/value array
 		if (Array.isArray(projection))
@@ -303,8 +271,8 @@ export default class DataModule extends BaseModule {
 			flattenedProjection = Object.entries(projection);
 
 		// Go through our projection array, and recursively check if there is another layer we need to flatten
-		flattenedProjection = flattenedProjection.reduce(
-			(currentEntries, [key, value]) => {
+		const newProjection: [string, boolean][] = flattenedProjection.reduce(
+			(currentEntries: [string, boolean][], [key, value]) => {
 				if (typeof value === "object") {
 					let flattenedValue = this.flattenProjection(value);
 					flattenedValue = flattenedValue.map(
@@ -320,7 +288,7 @@ export default class DataModule extends BaseModule {
 			[]
 		);
 
-		return flattenedProjection;
+		return newProjection;
 	}
 
 	/**
@@ -334,8 +302,8 @@ export default class DataModule extends BaseModule {
 	 * @returns
 	 */
 	private async parseFindProjection(
-		projection: any,
-		schema: any,
+		projection: NormalizedProjection,
+		schema: Document,
 		allowedRestricted: any
 	) {
 		// The mongo projection object we're going to build
@@ -427,7 +395,10 @@ export default class DataModule extends BaseModule {
 	 * @param property - Property name
 	 * @returns
 	 */
-	private allowedByProjection(projection: any, property: string) {
+	private allowedByProjection(
+		projection: NormalizedProjection,
+		property: string
+	) {
 		const obj = Object.fromEntries(projection.projection);
 
 		if (projection.mode === "excludeAllBut") {
@@ -465,8 +436,11 @@ export default class DataModule extends BaseModule {
 	 * @param key - The property key
 	 * @returns Array or Object
 	 */
-	private getDeeperProjection(projection: any, currentKey: string) {
-		const newProjection = projection.projection
+	private getDeeperProjection(
+		projection: NormalizedProjection,
+		currentKey: string
+	): NormalizedProjection {
+		const newProjection: [string, boolean][] = projection.projection
 			// Go through all key/values
 			.map(([key, value]) => {
 				// If a key has no ".", it has no deeper level, so return false
@@ -486,7 +460,8 @@ export default class DataModule extends BaseModule {
 				return [lowerKey, value];
 			})
 			// Filter out any false's, so only key/value pairs remain
-			.filter(entries => entries);
+			// .filter<[string, boolean]>(entries => !!entries);
+			.filter((entries): entries is [string, boolean] => !!entries);
 
 		// Return the new projection with the projection array, and the same existing mode for the projection
 		return { projection: newProjection, mode: projection.mode };
@@ -533,7 +508,7 @@ export default class DataModule extends BaseModule {
 		return newAllowedRestricted;
 	}
 
-	private getCastedValue(value, schemaType) {
+	private getCastedValue(value, schemaType: Types) {
 		if (schemaType === Types.String) {
 			// Check if value is a string, and if not, convert the value to a string
 			const castedValue =
@@ -596,13 +571,13 @@ export default class DataModule extends BaseModule {
 	 */
 	private async parseFindFilter(
 		filter: any,
-		schema: any,
+		schema: Document,
 		allowedRestricted: boolean | string[] | null | undefined,
 		options?: {
 			operators?: boolean;
 		}
 	): Promise<{
-		mongoFilter: any;
+		mongoFilter;
 		containsRestrictedProperties: boolean;
 		canCache: boolean;
 	}> {
@@ -622,7 +597,7 @@ export default class DataModule extends BaseModule {
 		// Whether to parse operators or not
 		const operators = !(options && options.operators === false);
 		// The MongoDB filter we're building
-		const mongoFilter: any = {};
+		const mongoFilter = {};
 		// If the filter references any properties that are restricted, this will be true, so that find knows not to cache the query object
 		let containsRestrictedProperties = false;
 		// Whether this filter is cachable or not
@@ -922,7 +897,7 @@ export default class DataModule extends BaseModule {
 	private async stripDocument(
 		document: any,
 		schema: any,
-		projection: any,
+		projection: NormalizedProjection,
 		allowedRestricted: boolean | string[] | null | undefined
 	) {
 		// TODO possibly do different things with required properties?
@@ -1099,7 +1074,7 @@ export default class DataModule extends BaseModule {
 		}: {
 			collection: CollectionNameType;
 			filter: Record<string, any>;
-			projection?: Record<string, any> | string[];
+			projection?: Projection;
 			allowedRestricted?: boolean | string[];
 			values?: Record<string, any>;
 			limit?: number;
@@ -1111,9 +1086,9 @@ export default class DataModule extends BaseModule {
 			let queryHash: string | null = null;
 			let cacheable = useCache !== false;
 
-			let schema;
+			let schema: Schema;
 
-			let normalizedProjection;
+			let normalizedProjection: NormalizedProjection;
 
 			let mongoFilter;
 			let mongoProjection;