Browse Source

fix: a bunch more TS fixes

Kristian Vos 1 year ago
parent
commit
a3440bc5a7

+ 1 - 0
backend/src/@types/mongoose-update-versioning.d.ts

@@ -0,0 +1 @@
+declare module "mongoose-update-versioning";

+ 13 - 5
backend/src/JobContext.ts

@@ -4,6 +4,10 @@ import { Log } from "@/LogBook";
 import { JobOptions } from "@/types/JobOptions";
 import DataModule from "@/modules/DataModule";
 import { UserModel } from "@/modules/DataModule/models/users/schema";
+import { JobDerived } from "./types/JobDerived";
+import assertJobDerived from "./utils/assertJobDerived";
+import { GetModelPermissionsResult } from "./modules/DataModule/models/users/jobs/GetModelPermissions";
+import { GetPermissionsResult } from "./modules/DataModule/models/users/jobs/GetPermissions";
 
 export default class JobContext {
 	public readonly job: Job;
@@ -54,11 +58,13 @@ export default class JobContext {
 	}
 
 	public executeJob(
-		JobClass: typeof Job,
+		JobClass: Function,
 		payload?: unknown,
 		options?: JobOptions
 	) {
-		return new JobClass(payload, {
+		assertJobDerived(JobClass);
+
+		return new (JobClass as JobDerived)(payload, {
 			session: this._session,
 			socketId: this._socketId,
 			...(options ?? {})
@@ -95,16 +101,18 @@ export default class JobContext {
 				"users.getModelPermissions"
 			);
 
-			const permissions = await this.executeJob(GetModelPermissions, {
+			const permissions = (await this.executeJob(GetModelPermissions, {
 				modelName: modelOrJobName,
 				modelId
-			});
+			})) as GetModelPermissionsResult;
 
 			hasPermission = permissions[`data.${modelOrJobName}.${jobName}`];
 		} else {
 			const GetPermissions = DataModule.getJob("users.getPermissions");
 
-			const permissions = await this.executeJob(GetPermissions);
+			const permissions = (await this.executeJob(
+				GetPermissions
+			)) as GetPermissionsResult;
 
 			hasPermission = permissions[permission];
 		}

+ 8 - 4
backend/src/JobQueue.ts

@@ -1,6 +1,8 @@
 import Job, { JobStatus } from "@/Job";
 import { JobOptions } from "@/types/JobOptions";
 import JobStatistics, { JobStatisticsType } from "./JobStatistics";
+import { JobDerived } from "./types/JobDerived";
+import assertJobDerived from "./utils/assertJobDerived";
 
 export class JobQueue {
 	private _concurrency: number;
@@ -54,12 +56,13 @@ export class JobQueue {
 	 * runJob - Run a job
 	 */
 	public async runJob(
-		JobClass: typeof Job,
+		JobClass: Function,
 		payload?: unknown,
 		options?: JobOptions
 	): Promise<unknown> {
+		assertJobDerived(JobClass);
 		return new Promise<unknown>((resolve, reject) => {
-			this.queueJob(JobClass, payload, options)
+			this.queueJob(JobClass as JobDerived, payload, options)
 				.then(uuid => {
 					this._callbacks[uuid] = { resolve, reject };
 				})
@@ -71,11 +74,12 @@ export class JobQueue {
 	 * queueJob - Queue a job
 	 */
 	public async queueJob(
-		JobClass: typeof Job,
+		JobClass: Function,
 		payload?: unknown,
 		options?: JobOptions
 	): Promise<string> {
-		const job = new JobClass(payload, options);
+		assertJobDerived(JobClass);
+		const job = new (JobClass as JobDerived)(payload, options);
 
 		JobStatistics.updateStats(job.getPath(), JobStatisticsType.QUEUED);
 

+ 8 - 3
backend/src/LogBook.ts

@@ -132,9 +132,12 @@ export class LogBook {
 			}
 		);
 
+		const jobName =
+			logObject.data && "jobName" in logObject.data
+				? logObject.data.jobName
+				: null;
 		// Title will be the jobname, or category of jobname is undefined
-		const title =
-			logObject.data?.jobName ?? logObject.category ?? undefined;
+		const title = jobName ?? logObject.category ?? undefined;
 
 		// If memory is not excluded and memory is enabled, store the log object in the memory (logs array) of this logbook instance
 		if (!exclude.memory && this._outputs.memory.enabled)
@@ -143,7 +146,9 @@ export class LogBook {
 		// If console is not excluded, format the log object, and then write the formatted message to the console
 		if (!exclude.console) {
 			const message = this._formatMessage(logObject, String(title));
-			const logArgs: (string | Record<string, unknown>)[] = [message];
+			const logArgs: (string | Record<string, unknown> | Error)[] = [
+				message
+			];
 
 			// Append logObject data, if enabled and it's not falsy
 			if (this._outputs.console.data && logObject.data)

+ 12 - 2
backend/src/modules/DataModule.ts

@@ -293,7 +293,12 @@ export class DataModule extends BaseModule {
 				)
 			);
 		} catch (error) {
-			if (error.code === "ENOENT") return [];
+			if (
+				error instanceof Error &&
+				"code" in error &&
+				error.code === "ENOENT"
+			)
+				return [];
 
 			throw error;
 		}
@@ -341,7 +346,12 @@ export class DataModule extends BaseModule {
 					)
 				);
 			} catch (error) {
-				if (error.code === "ENOENT") return;
+				if (
+					error instanceof Error &&
+					"code" in error &&
+					error.code === "ENOENT"
+				)
+					return;
 
 				throw error;
 			}

+ 10 - 6
backend/src/modules/DataModule/models/users/jobs/GetModelPermissions.ts

@@ -2,10 +2,12 @@ import { isObjectIdOrHexString } from "mongoose";
 import CacheModule from "@/modules/CacheModule";
 import DataModule from "@/modules/DataModule";
 import ModuleManager from "@/ModuleManager";
-import GetPermissions from "./GetPermissions";
+import GetPermissions, { GetPermissionsResult } from "./GetPermissions";
 import DataModuleJob from "@/modules/DataModule/DataModuleJob";
 import { forEachIn } from "@/utils/forEachIn";
 
+export type GetModelPermissionsResult = Record<string, boolean>;
+
 export default class GetModelPermissions extends DataModuleJob {
 	protected static _modelName = "users";
 
@@ -28,11 +30,13 @@ export default class GetModelPermissions extends DataModuleJob {
 
 	protected override async _authorize() {}
 
-	protected async _execute() {
+	protected async _execute(): Promise<GetModelPermissionsResult> {
 		const { modelName, modelId } = this._payload;
 
 		const user = await this._context.getUser().catch(() => null);
-		const permissions = await this._context.executeJob(GetPermissions);
+		const permissions = (await this._context.executeJob(
+			GetPermissions
+		)) as GetPermissionsResult;
 
 		let cacheKey = `model-permissions.${modelName}`;
 
@@ -53,14 +57,14 @@ export default class GetModelPermissions extends DataModuleJob {
 
 		if (modelId && !model) throw new Error("Model not found");
 
-		const jobs = await forEachIn(
+		const jobs = (await forEachIn(
 			Object.entries(
 				ModuleManager.getModule("data")?.getJobs() ?? {}
 			).filter(
 				([jobName]) =>
 					jobName.startsWith(modelName.toString()) &&
 					(modelId ? true : !jobName.endsWith("ById"))
-			),
+			) as [string, typeof DataModuleJob][],
 			async ([jobName, Job]) => {
 				jobName = `data.${jobName}`;
 
@@ -79,7 +83,7 @@ export default class GetModelPermissions extends DataModuleJob {
 
 				return [jobName, !!hasPermission];
 			}
-		);
+		)) as [string, boolean][];
 
 		const modelPermissions = Object.fromEntries(jobs);
 

+ 3 - 1
backend/src/modules/DataModule/models/users/jobs/GetPermissions.ts

@@ -3,6 +3,8 @@ import permissions from "@/modules/DataModule/models/users/permissions";
 import { UserRole } from "../UserRole";
 import DataModuleJob from "@/modules/DataModule/DataModuleJob";
 
+export type GetPermissionsResult = Record<string, boolean>;
+
 export default class GetPermissions extends DataModuleJob {
 	protected static _modelName = "users";
 
@@ -10,7 +12,7 @@ export default class GetPermissions extends DataModuleJob {
 
 	protected override async _authorize() {}
 
-	protected async _execute() {
+	protected async _execute(): Promise<GetPermissionsResult> {
 		const user = await this._context.getUser().catch(() => null);
 
 		if (!user) return permissions.guest;

+ 40 - 18
backend/src/modules/EventsModule.ts

@@ -1,13 +1,29 @@
-import { createClient, RedisClientType } from "redis";
+import {
+	createClient,
+	RedisClientOptions,
+	RedisClientType,
+	RedisDefaultModules,
+	RedisFunctions,
+	RedisModules,
+	RedisScripts
+} from "redis";
 import config from "config";
 import BaseModule, { ModuleStatus } from "@/BaseModule";
 import WebSocketModule from "./WebSocketModule";
 import { forEachIn } from "@/utils/forEachIn";
 
 export class EventsModule extends BaseModule {
-	private _pubClient?: RedisClientType;
+	private _pubClient?: RedisClientType<
+		RedisDefaultModules & RedisModules,
+		RedisFunctions,
+		RedisScripts
+	>;
 
-	private _subClient?: RedisClientType;
+	private _subClient?: RedisClientType<
+		RedisDefaultModules & RedisModules,
+		RedisFunctions,
+		RedisScripts
+	>;
 
 	private _subscriptions: Record<string, ((message: any) => Promise<void>)[]>;
 
@@ -49,23 +65,25 @@ export class EventsModule extends BaseModule {
 	 */
 	private async _createPubClient() {
 		this._pubClient = createClient({
-			...config.get("redis"),
-			reconnectStrategy: (retries: number, error) => {
-				if (
-					retries >= 10 ||
-					![ModuleStatus.STARTING, ModuleStatus.STARTED].includes(
-						this.getStatus()
+			...config.get<RedisClientOptions>("redis"),
+			socket: {
+				reconnectStrategy: (retries: number, error) => {
+					if (
+						retries >= 10 ||
+						![ModuleStatus.STARTING, ModuleStatus.STARTED].includes(
+							this.getStatus()
+						)
 					)
-				)
-					return false;
+						return false;
 
-				this.log({
-					type: "debug",
-					message: `Redis reconnect attempt ${retries}`,
-					data: error
-				});
+					this.log({
+						type: "debug",
+						message: `Redis reconnect attempt ${retries}`,
+						data: error
+					});
 
-				return Math.min(retries * 50, 500);
+					return Math.min(retries * 50, 500);
+				}
 			}
 		});
 
@@ -336,7 +354,11 @@ export class EventsModule extends BaseModule {
 
 	public async subscribeSocket(channel: string, socketId: string) {
 		if (!this._socketSubscriptions[channel]) {
-			await this.subscribe("event", channel, () => {});
+			await this.subscribe(
+				"event",
+				channel,
+				() => new Promise<void>(resolve => resolve())
+			);
 
 			this._socketSubscriptions[channel] = new Set();
 		}

+ 4 - 1
backend/src/modules/WebSocketModule.ts

@@ -12,6 +12,7 @@ import { UserModel } from "./DataModule/models/users/schema";
 import { SessionModel } from "./DataModule/models/sessions/schema";
 import EventsModule from "./EventsModule";
 import { forEachIn } from "@/utils/forEachIn";
+import { getErrorMessage } from "@/utils/getErrorMessage";
 
 export class WebSocketModule extends BaseModule {
 	private _httpServer?: Server;
@@ -260,6 +261,8 @@ export class WebSocketModule extends BaseModule {
 						updatedAt: Date.now()
 					}
 				);
+
+				if (!session) throw new Error("Session not found.");
 			}
 
 			await JobQueue.queueJob(Job, payload, {
@@ -268,7 +271,7 @@ export class WebSocketModule extends BaseModule {
 				callbackRef
 			});
 		} catch (error) {
-			const message = error?.message ?? error;
+			const message = getErrorMessage(error);
 
 			if (callbackRef)
 				socket.dispatch("jobCallback", callbackRef, {

+ 16 - 0
backend/src/types/JobDerived.ts

@@ -0,0 +1,16 @@
+import Job from "@/Job";
+
+type JobConstructorParameters = ConstructorParameters<typeof Job>;
+// Borrowed from https://dev.to/futuresight/how-2-typescript-get-the-last-item-type-from-a-tuple-of-types-3fh3#comment-gb5d
+type DropFirstInTuple<T extends any[]> = ((...args: T) => any) extends (
+	arg: any,
+	...rest: infer U
+) => any
+	? U
+	: T;
+type DerivedJobConstructorParameters =
+	DropFirstInTuple<JobConstructorParameters>;
+
+export interface JobDerived extends Job {
+	new (...args: DerivedJobConstructorParameters): Job & typeof Job;
+}

+ 12 - 0
backend/src/utils/assertJobDerived.ts

@@ -0,0 +1,12 @@
+import Job from "@/Job";
+
+export default (JobClass: Function) => {
+	// Make sure the provided JobClass has Job as the parent somewhere as a parent. Not Job itself, as that constructor requires an additional constructor parameter
+	// So any class that extends Job, or that extends another class that extends Job, will be allowed.
+	let classPrototype = Object.getPrototypeOf(JobClass);
+	while (classPrototype) {
+		if (classPrototype === Job) break;
+		classPrototype = Object.getPrototypeOf(classPrototype);
+	}
+	if (!classPrototype) throw new Error("Provided job class is not a job.");
+};

+ 1 - 1
backend/src/utils/forEachIn.ts

@@ -1,5 +1,5 @@
 export const forEachIn = async <
-	ItemsType extends Array<any>,
+	ItemsType extends Array<unknown>,
 	CallbackType extends (
 		item: ItemsType[number],
 		index: number

+ 98 - 97
backend/tsconfig.json

@@ -1,107 +1,108 @@
 {
-  "compilerOptions": {
-    /* Visit https://aka.ms/tsconfig to read more about this file */
+	"compilerOptions": {
+		/* Visit https://aka.ms/tsconfig to read more about this file */
 
-    /* Projects */
-    // "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
-    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
-    // "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
-    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
-    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
-    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
+		/* Projects */
+		// "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
+		// "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
+		// "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
+		// "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
+		// "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
+		// "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
 
-    /* Language and Environment */
-    "target": "es2022",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
-    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
-    // "jsx": "preserve",                                /* Specify what JSX code is generated. */
-    // "experimentalDecorators": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */
-    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
-    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
-    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
-    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
-    // "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
-    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
-    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
-    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
+		/* Language and Environment */
+		"target": "es2022" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
+		// "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+		// "jsx": "preserve",                                /* Specify what JSX code is generated. */
+		// "experimentalDecorators": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */
+		// "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
+		// "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
+		// "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+		// "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
+		// "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
+		// "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
+		// "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
+		// "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
 
-    /* Modules */
-    "module": "commonjs",                                /* Specify what module code is generated. */
-    // "rootDir": "./",                                  /* Specify the root folder within your source files. */
-    // "moduleResolution": "node",                       /* Specify how TypeScript looks up a file from a given module specifier. */
-    "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
-    "paths": {
-      /* Specify a set of entries that re-map imports to additional lookup locations. */
-      "@/*": ["src/*"],
-      "@models/*": ["src/modules/DataModule/models/*"]
-    },
-    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
-    // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
-    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
-    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
-    // "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
-    // "resolveJsonModule": true,                        /* Enable importing .json files. */
-    // "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
+		/* Modules */
+		"module": "commonjs" /* Specify what module code is generated. */,
+		// "rootDir": "./",                                  /* Specify the root folder within your source files. */
+		// "moduleResolution": "node",                       /* Specify how TypeScript looks up a file from a given module specifier. */
+		"baseUrl": "./" /* Specify the base directory to resolve non-relative module names. */,
+		"paths": {
+			/* Specify a set of entries that re-map imports to additional lookup locations. */
+			"@/*": ["src/*"],
+			"@models/*": ["src/modules/DataModule/models/*"]
+		},
+		// "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
+		// "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
+		// "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
+		// "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
+		// "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
+		// "resolveJsonModule": true,                        /* Enable importing .json files. */
+		// "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
 
-    /* JavaScript Support */
-    "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
-    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
-    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+		/* JavaScript Support */
+		"allowJs": true /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */,
+		// "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
+		// "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
 
-    /* Emit */
-    // "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
-    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
-    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
-    // "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
-    // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
-    "outDir": "./build",                                   /* Specify an output folder for all emitted files. */
-    // "removeComments": true,                           /* Disable emitting comments. */
-    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
-    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
-    // "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types. */
-    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
-    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
-    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
-    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
-    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
-    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
-    // "newLine": "crlf",                                /* Set the newline character for emitting files. */
-    // "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
-    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
-    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
-    // "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
-    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
-    // "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+		/* Emit */
+		// "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+		// "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
+		// "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
+		// "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
+		// "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
+		"outDir": "./build" /* Specify an output folder for all emitted files. */,
+		// "removeComments": true,                           /* Disable emitting comments. */
+		// "noEmit": true,                                   /* Disable emitting files from a compilation. */
+		// "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+		// "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types. */
+		// "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+		// "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
+		// "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
+		// "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
+		// "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
+		// "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+		// "newLine": "crlf",                                /* Set the newline character for emitting files. */
+		// "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
+		// "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
+		// "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
+		// "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
+		// "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
+		// "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
 
-    /* Interop Constraints */
-    // "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
-    // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
-    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
-    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
-    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
+		/* Interop Constraints */
+		// "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
+		// "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
+		"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
+		// "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+		"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
 
-    /* Type Checking */
-    "strict": true,                                      /* Enable all strict type-checking options. */
-    // "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
-    // "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
-    // "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
-    // "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
-    // "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
-    // "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */
-    // "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
-    // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
-    // "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */
-    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */
-    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
-    // "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
-    // "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
-    // "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */
-    // "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
-    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
-    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
-    // "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */
+		/* Type Checking */
+		"strict": true /* Enable all strict type-checking options. */,
+		// "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
+		// "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
+		// "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+		// "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
+		// "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
+		// "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */
+		// "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
+		// "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
+		// "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */
+		// "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */
+		// "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
+		// "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
+		// "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
+		// "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */
+		// "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
+		// "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
+		// "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
+		// "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */
 
-    /* Completeness */
-    // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
-    "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
-  }
+		/* Completeness */
+		// "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
+		"skipLibCheck": true /* Skip type checking all .d.ts files. */,
+		"pretty": true
+	}
 }