diff --git a/backend/src/app.ts b/backend/src/app.ts index c8658cd5..f4c941e5 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -26,7 +26,7 @@ app.use('/api', apiRouter); // Swagger app.use('/api-docs', swaggerUi.serve, swaggerMiddleware); -async function startServer() { +async function startServer(): Promise { await initORM(); app.listen(port, () => { diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index 96cdd4dd..d71571e5 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -47,7 +47,7 @@ export async function getStudentHandler(req: Request, res: Response): Promise { const userData = req.body as StudentDTO; if (!userData.username || !userData.firstName || !userData.lastName) { @@ -61,7 +61,7 @@ export async function createStudentHandler(req: Request, res: Response) { res.status(201).json(newUser); } -export async function deleteStudentHandler(req: Request, res: Response) { +export async function deleteStudentHandler(req: Request, res: Response): Promise { const username = req.params.username; if (!username) { diff --git a/backend/src/controllers/submissions.ts b/backend/src/controllers/submissions.ts index 1e66dbe9..cb8f2de2 100644 --- a/backend/src/controllers/submissions.ts +++ b/backend/src/controllers/submissions.ts @@ -30,7 +30,7 @@ export async function getSubmissionHandler(req: Request, res: res.json(submission); } -export async function createSubmissionHandler(req: Request, res: Response) { +export async function createSubmissionHandler(req: Request, res: Response): Promise { const submissionDTO = req.body as SubmissionDTO; const submission = await createSubmission(submissionDTO); @@ -42,7 +42,7 @@ export async function createSubmissionHandler(req: Request, res: Response) { } } -export async function deleteSubmissionHandler(req: Request, res: Response) { +export async function deleteSubmissionHandler(req: Request, res: Response): Promise { const hruid = req.params.hruid; const submissionNumber = +req.params.id; diff --git a/backend/src/controllers/teachers.ts b/backend/src/controllers/teachers.ts index 7bcbb5f4..e5f1fc87 100644 --- a/backend/src/controllers/teachers.ts +++ b/backend/src/controllers/teachers.ts @@ -50,7 +50,7 @@ export async function getTeacherHandler(req: Request, res: Response): Promise { const userData = req.body as TeacherDTO; if (!userData.username || !userData.firstName || !userData.lastName) { @@ -64,7 +64,7 @@ export async function createTeacherHandler(req: Request, res: Response) { res.status(201).json(newUser); } -export async function deleteTeacherHandler(req: Request, res: Response) { +export async function deleteTeacherHandler(req: Request, res: Response): Promise { const username = req.params.username; if (!username) { diff --git a/backend/src/controllers/themes.ts b/backend/src/controllers/themes.ts index 61a1a834..1ef113cd 100644 --- a/backend/src/controllers/themes.ts +++ b/backend/src/controllers/themes.ts @@ -8,7 +8,7 @@ interface Translations { }; } -export function getThemes(req: Request, res: Response) { +export function getThemes(req: Request, res: Response): void { const language = (req.query.language as string)?.toLowerCase() || 'nl'; const translations = loadTranslations(language); const themeList = themes.map((theme) => ({ @@ -21,7 +21,7 @@ export function getThemes(req: Request, res: Response) { res.json(themeList); } -export function getThemeByTitle(req: Request, res: Response) { +export function getThemeByTitle(req: Request, res: Response): void { const themeKey = req.params.theme; const theme = themes.find((t) => t.title === themeKey); diff --git a/backend/src/controllers/users.ts b/backend/src/controllers/users.ts index ac3f824b..7706e2ee 100644 --- a/backend/src/controllers/users.ts +++ b/backend/src/controllers/users.ts @@ -47,7 +47,7 @@ export async function getUserHandler(req: Request, res: Response } } -export async function createUserHandler(req: Request, res: Response, service: UserService, userClass: new () => T) { +export async function createUserHandler(req: Request, res: Response, service: UserService, userClass: new () => T): Promise { try { getLogger().debug({ req: req }); const userData = req.body as UserDTO; @@ -67,7 +67,7 @@ export async function createUserHandler(req: Request, res: Respo } } -export async function deleteUserHandler(req: Request, res: Response, service: UserService) { +export async function deleteUserHandler(req: Request, res: Response, service: UserService): Promise { try { const username = req.params.username; diff --git a/backend/src/data/assignments/assignment-repository.ts b/backend/src/data/assignments/assignment-repository.ts index c3c457d3..3de5031d 100644 --- a/backend/src/data/assignments/assignment-repository.ts +++ b/backend/src/data/assignments/assignment-repository.ts @@ -3,13 +3,13 @@ import { Assignment } from '../../entities/assignments/assignment.entity.js'; import { Class } from '../../entities/classes/class.entity.js'; export class AssignmentRepository extends DwengoEntityRepository { - public findByClassAndId(within: Class, id: number): Promise { + public async findByClassAndId(within: Class, id: number): Promise { return this.findOne({ within: within, id: id }); } - public findAllAssignmentsInClass(within: Class): Promise { + public async findAllAssignmentsInClass(within: Class): Promise { return this.findAll({ where: { within: within } }); } - public deleteByClassAndId(within: Class, id: number): Promise { + public async deleteByClassAndId(within: Class, id: number): Promise { return this.deleteWhere({ within: within, id: id }); } } diff --git a/backend/src/data/assignments/group-repository.ts b/backend/src/data/assignments/group-repository.ts index eb1b09e2..f06080f7 100644 --- a/backend/src/data/assignments/group-repository.ts +++ b/backend/src/data/assignments/group-repository.ts @@ -4,7 +4,7 @@ import { Assignment } from '../../entities/assignments/assignment.entity.js'; import { Student } from '../../entities/users/student.entity.js'; export class GroupRepository extends DwengoEntityRepository { - public findByAssignmentAndGroupNumber(assignment: Assignment, groupNumber: number): Promise { + public async findByAssignmentAndGroupNumber(assignment: Assignment, groupNumber: number): Promise { return this.findOne( { assignment: assignment, @@ -13,16 +13,16 @@ export class GroupRepository extends DwengoEntityRepository { { populate: ['members'] } ); } - public findAllGroupsForAssignment(assignment: Assignment): Promise { + public async findAllGroupsForAssignment(assignment: Assignment): Promise { return this.findAll({ where: { assignment: assignment }, populate: ['members'], }); } - public findAllGroupsWithStudent(student: Student): Promise { + public async findAllGroupsWithStudent(student: Student): Promise { return this.find({ members: student }, { populate: ['members'] }); } - public deleteByAssignmentAndGroupNumber(assignment: Assignment, groupNumber: number) { + public async deleteByAssignmentAndGroupNumber(assignment: Assignment, groupNumber: number): Promise { return this.deleteWhere({ assignment: assignment, groupNumber: groupNumber, diff --git a/backend/src/data/assignments/submission-repository.ts b/backend/src/data/assignments/submission-repository.ts index 251823fa..f5090adc 100644 --- a/backend/src/data/assignments/submission-repository.ts +++ b/backend/src/data/assignments/submission-repository.ts @@ -5,7 +5,10 @@ import { LearningObjectIdentifier } from '../../entities/content/learning-object import { Student } from '../../entities/users/student.entity.js'; export class SubmissionRepository extends DwengoEntityRepository { - public findSubmissionByLearningObjectAndSubmissionNumber(loId: LearningObjectIdentifier, submissionNumber: number): Promise { + public async findSubmissionByLearningObjectAndSubmissionNumber( + loId: LearningObjectIdentifier, + submissionNumber: number + ): Promise { return this.findOne({ learningObjectHruid: loId.hruid, learningObjectLanguage: loId.language, @@ -14,7 +17,7 @@ export class SubmissionRepository extends DwengoEntityRepository { }); } - public findMostRecentSubmissionForStudent(loId: LearningObjectIdentifier, submitter: Student): Promise { + public async findMostRecentSubmissionForStudent(loId: LearningObjectIdentifier, submitter: Student): Promise { return this.findOne( { learningObjectHruid: loId.hruid, @@ -26,7 +29,7 @@ export class SubmissionRepository extends DwengoEntityRepository { ); } - public findMostRecentSubmissionForGroup(loId: LearningObjectIdentifier, group: Group): Promise { + public async findMostRecentSubmissionForGroup(loId: LearningObjectIdentifier, group: Group): Promise { return this.findOne( { learningObjectHruid: loId.hruid, @@ -38,15 +41,15 @@ export class SubmissionRepository extends DwengoEntityRepository { ); } - public findAllSubmissionsForGroup(group: Group): Promise { + public async findAllSubmissionsForGroup(group: Group): Promise { return this.find({ onBehalfOf: group }); } - public findAllSubmissionsForStudent(student: Student): Promise { + public async findAllSubmissionsForStudent(student: Student): Promise { return this.find({ submitter: student }); } - public deleteSubmissionByLearningObjectAndSubmissionNumber(loId: LearningObjectIdentifier, submissionNumber: number): Promise { + public async deleteSubmissionByLearningObjectAndSubmissionNumber(loId: LearningObjectIdentifier, submissionNumber: number): Promise { return this.deleteWhere({ learningObjectHruid: loId.hruid, learningObjectLanguage: loId.language, diff --git a/backend/src/data/classes/class-join-request-repository.ts b/backend/src/data/classes/class-join-request-repository.ts index c1443c1c..1cd0288c 100644 --- a/backend/src/data/classes/class-join-request-repository.ts +++ b/backend/src/data/classes/class-join-request-repository.ts @@ -4,13 +4,13 @@ import { ClassJoinRequest } from '../../entities/classes/class-join-request.enti import { Student } from '../../entities/users/student.entity.js'; export class ClassJoinRequestRepository extends DwengoEntityRepository { - public findAllRequestsBy(requester: Student): Promise { + public async findAllRequestsBy(requester: Student): Promise { return this.findAll({ where: { requester: requester } }); } - public findAllOpenRequestsTo(clazz: Class): Promise { + public async findAllOpenRequestsTo(clazz: Class): Promise { return this.findAll({ where: { class: clazz } }); } - public deleteBy(requester: Student, clazz: Class): Promise { + public async deleteBy(requester: Student, clazz: Class): Promise { return this.deleteWhere({ requester: requester, class: clazz }); } } diff --git a/backend/src/data/classes/class-repository.ts b/backend/src/data/classes/class-repository.ts index 0ceed98e..f4e0723f 100644 --- a/backend/src/data/classes/class-repository.ts +++ b/backend/src/data/classes/class-repository.ts @@ -4,20 +4,20 @@ import { Student } from '../../entities/users/student.entity.js'; import { Teacher } from '../../entities/users/teacher.entity'; export class ClassRepository extends DwengoEntityRepository { - public findById(id: string): Promise { + public async findById(id: string): Promise { return this.findOne({ classId: id }, { populate: ['students', 'teachers'] }); } - public deleteById(id: string): Promise { + public async deleteById(id: string): Promise { return this.deleteWhere({ classId: id }); } - public findByStudent(student: Student): Promise { + public async findByStudent(student: Student): Promise { return this.find( { students: student }, { populate: ['students', 'teachers'] } // Voegt student en teacher objecten toe ); } - public findByTeacher(teacher: Teacher): Promise { + public async findByTeacher(teacher: Teacher): Promise { return this.find({ teachers: teacher }, { populate: ['students', 'teachers'] }); } } diff --git a/backend/src/data/classes/teacher-invitation-repository.ts b/backend/src/data/classes/teacher-invitation-repository.ts index 6b94deec..ce059ca8 100644 --- a/backend/src/data/classes/teacher-invitation-repository.ts +++ b/backend/src/data/classes/teacher-invitation-repository.ts @@ -4,16 +4,16 @@ import { TeacherInvitation } from '../../entities/classes/teacher-invitation.ent import { Teacher } from '../../entities/users/teacher.entity.js'; export class TeacherInvitationRepository extends DwengoEntityRepository { - public findAllInvitationsForClass(clazz: Class): Promise { + public async findAllInvitationsForClass(clazz: Class): Promise { return this.findAll({ where: { class: clazz } }); } - public findAllInvitationsBy(sender: Teacher): Promise { + public async findAllInvitationsBy(sender: Teacher): Promise { return this.findAll({ where: { sender: sender } }); } - public findAllInvitationsFor(receiver: Teacher): Promise { + public async findAllInvitationsFor(receiver: Teacher): Promise { return this.findAll({ where: { receiver: receiver } }); } - public deleteBy(clazz: Class, sender: Teacher, receiver: Teacher): Promise { + public async deleteBy(clazz: Class, sender: Teacher, receiver: Teacher): Promise { return this.deleteWhere({ sender: sender, receiver: receiver, diff --git a/backend/src/data/content/attachment-repository.ts b/backend/src/data/content/attachment-repository.ts index 95c5ab1c..73baa943 100644 --- a/backend/src/data/content/attachment-repository.ts +++ b/backend/src/data/content/attachment-repository.ts @@ -4,7 +4,7 @@ import { Language } from '../../entities/content/language'; import { LearningObjectIdentifier } from '../../entities/content/learning-object-identifier'; export class AttachmentRepository extends DwengoEntityRepository { - public findByLearningObjectIdAndName(learningObjectId: LearningObjectIdentifier, name: string): Promise { + public async findByLearningObjectIdAndName(learningObjectId: LearningObjectIdentifier, name: string): Promise { return this.findOne({ learningObject: { hruid: learningObjectId.hruid, @@ -15,7 +15,11 @@ export class AttachmentRepository extends DwengoEntityRepository { }); } - public findByMostRecentVersionOfLearningObjectAndName(hruid: string, language: Language, attachmentName: string): Promise { + public async findByMostRecentVersionOfLearningObjectAndName( + hruid: string, + language: Language, + attachmentName: string + ): Promise { return this.findOne( { learningObject: { diff --git a/backend/src/data/content/learning-object-repository.ts b/backend/src/data/content/learning-object-repository.ts index 49b4c536..4684c6cc 100644 --- a/backend/src/data/content/learning-object-repository.ts +++ b/backend/src/data/content/learning-object-repository.ts @@ -5,7 +5,7 @@ import { Language } from '../../entities/content/language.js'; import { Teacher } from '../../entities/users/teacher.entity.js'; export class LearningObjectRepository extends DwengoEntityRepository { - public findByIdentifier(identifier: LearningObjectIdentifier): Promise { + public async findByIdentifier(identifier: LearningObjectIdentifier): Promise { return this.findOne( { hruid: identifier.hruid, @@ -18,7 +18,7 @@ export class LearningObjectRepository extends DwengoEntityRepository { return this.findOne( { hruid: hruid, @@ -33,7 +33,7 @@ export class LearningObjectRepository extends DwengoEntityRepository { + public async findAllByTeacher(teacher: Teacher): Promise { return this.find( { admins: teacher }, { populate: ['admins'] } // Make sure to load admin relations diff --git a/backend/src/data/content/learning-path-repository.ts b/backend/src/data/content/learning-path-repository.ts index a2f9b47e..e34508ec 100644 --- a/backend/src/data/content/learning-path-repository.ts +++ b/backend/src/data/content/learning-path-repository.ts @@ -3,7 +3,7 @@ import { LearningPath } from '../../entities/content/learning-path.entity.js'; import { Language } from '../../entities/content/language.js'; export class LearningPathRepository extends DwengoEntityRepository { - public findByHruidAndLanguage(hruid: string, language: Language): Promise { + public async findByHruidAndLanguage(hruid: string, language: Language): Promise { return this.findOne({ hruid: hruid, language: language }, { populate: ['nodes', 'nodes.transitions'] }); } diff --git a/backend/src/data/dwengo-entity-repository.ts b/backend/src/data/dwengo-entity-repository.ts index 6538d6f5..f64b8408 100644 --- a/backend/src/data/dwengo-entity-repository.ts +++ b/backend/src/data/dwengo-entity-repository.ts @@ -1,12 +1,12 @@ import { EntityRepository, FilterQuery } from '@mikro-orm/core'; export abstract class DwengoEntityRepository extends EntityRepository { - public async save(entity: T) { + public async save(entity: T): Promise { const em = this.getEntityManager(); em.persist(entity); await em.flush(); } - public async deleteWhere(query: FilterQuery) { + public async deleteWhere(query: FilterQuery): Promise { const toDelete = await this.findOne(query); const em = this.getEntityManager(); if (toDelete) { diff --git a/backend/src/data/questions/answer-repository.ts b/backend/src/data/questions/answer-repository.ts index a28342bd..a50bfd28 100644 --- a/backend/src/data/questions/answer-repository.ts +++ b/backend/src/data/questions/answer-repository.ts @@ -4,7 +4,7 @@ import { Question } from '../../entities/questions/question.entity.js'; import { Teacher } from '../../entities/users/teacher.entity.js'; export class AnswerRepository extends DwengoEntityRepository { - public createAnswer(answer: { toQuestion: Question; author: Teacher; content: string }): Promise { + public async createAnswer(answer: { toQuestion: Question; author: Teacher; content: string }): Promise { const answerEntity = this.create({ toQuestion: answer.toQuestion, author: answer.author, @@ -13,13 +13,13 @@ export class AnswerRepository extends DwengoEntityRepository { }); return this.insert(answerEntity); } - public findAllAnswersToQuestion(question: Question): Promise { + public async findAllAnswersToQuestion(question: Question): Promise { return this.findAll({ where: { toQuestion: question }, orderBy: { sequenceNumber: 'ASC' }, }); } - public removeAnswerByQuestionAndSequenceNumber(question: Question, sequenceNumber: number): Promise { + public async removeAnswerByQuestionAndSequenceNumber(question: Question, sequenceNumber: number): Promise { return this.deleteWhere({ toQuestion: question, sequenceNumber: sequenceNumber, diff --git a/backend/src/data/questions/question-repository.ts b/backend/src/data/questions/question-repository.ts index 9207e1dd..596b562c 100644 --- a/backend/src/data/questions/question-repository.ts +++ b/backend/src/data/questions/question-repository.ts @@ -5,7 +5,7 @@ import { Student } from '../../entities/users/student.entity.js'; import { LearningObject } from '../../entities/content/learning-object.entity.js'; export class QuestionRepository extends DwengoEntityRepository { - public createQuestion(question: { loId: LearningObjectIdentifier; author: Student; content: string }): Promise { + public async createQuestion(question: { loId: LearningObjectIdentifier; author: Student; content: string }): Promise { const questionEntity = this.create({ learningObjectHruid: question.loId.hruid, learningObjectLanguage: question.loId.language, @@ -21,7 +21,7 @@ export class QuestionRepository extends DwengoEntityRepository { questionEntity.content = question.content; return this.insert(questionEntity); } - public findAllQuestionsAboutLearningObject(loId: LearningObjectIdentifier): Promise { + public async findAllQuestionsAboutLearningObject(loId: LearningObjectIdentifier): Promise { return this.findAll({ where: { learningObjectHruid: loId.hruid, @@ -33,7 +33,7 @@ export class QuestionRepository extends DwengoEntityRepository { }, }); } - public removeQuestionByLearningObjectAndSequenceNumber(loId: LearningObjectIdentifier, sequenceNumber: number): Promise { + public async removeQuestionByLearningObjectAndSequenceNumber(loId: LearningObjectIdentifier, sequenceNumber: number): Promise { return this.deleteWhere({ learningObjectHruid: loId.hruid, learningObjectLanguage: loId.language, diff --git a/backend/src/data/repositories.ts b/backend/src/data/repositories.ts index cdeb50c1..852d9d6a 100644 --- a/backend/src/data/repositories.ts +++ b/backend/src/data/repositories.ts @@ -34,7 +34,7 @@ let entityManager: EntityManager | undefined; /** * Execute all the database operations within the function f in a single transaction. */ -export function transactional(f: () => Promise) { +export function transactional(f: () => Promise): void { entityManager?.transactional(f); } diff --git a/backend/src/data/users/student-repository.ts b/backend/src/data/users/student-repository.ts index 34b24b8b..2efca048 100644 --- a/backend/src/data/users/student-repository.ts +++ b/backend/src/data/users/student-repository.ts @@ -2,10 +2,10 @@ import { Student } from '../../entities/users/student.entity.js'; import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; export class StudentRepository extends DwengoEntityRepository { - public findByUsername(username: string): Promise { + public async findByUsername(username: string): Promise { return this.findOne({ username: username }); } - public deleteByUsername(username: string): Promise { + public async deleteByUsername(username: string): Promise { return this.deleteWhere({ username: username }); } } diff --git a/backend/src/data/users/teacher-repository.ts b/backend/src/data/users/teacher-repository.ts index 825b4d18..aa915627 100644 --- a/backend/src/data/users/teacher-repository.ts +++ b/backend/src/data/users/teacher-repository.ts @@ -2,10 +2,10 @@ import { Teacher } from '../../entities/users/teacher.entity.js'; import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; export class TeacherRepository extends DwengoEntityRepository { - public findByUsername(username: string): Promise { + public async findByUsername(username: string): Promise { return this.findOne({ username: username }); } - public deleteByUsername(username: string): Promise { + public async deleteByUsername(username: string): Promise { return this.deleteWhere({ username: username }); } } diff --git a/backend/src/data/users/user-repository.ts b/backend/src/data/users/user-repository.ts index 21497b79..44eb0bc7 100644 --- a/backend/src/data/users/user-repository.ts +++ b/backend/src/data/users/user-repository.ts @@ -2,10 +2,10 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { User } from '../../entities/users/user.entity.js'; export class UserRepository extends DwengoEntityRepository { - public findByUsername(username: string): Promise { + public async findByUsername(username: string): Promise { return this.findOne({ username } as Partial); } - public deleteByUsername(username: string): Promise { + public async deleteByUsername(username: string): Promise { return this.deleteWhere({ username } as Partial); } } diff --git a/backend/src/entities/content/learning-object-identifier.ts b/backend/src/entities/content/learning-object-identifier.ts index 3c020bd7..9234afa7 100644 --- a/backend/src/entities/content/learning-object-identifier.ts +++ b/backend/src/entities/content/learning-object-identifier.ts @@ -5,5 +5,7 @@ export class LearningObjectIdentifier { public hruid: string, public language: Language, public version: number - ) {} + ) { + // Do nothing + } } diff --git a/backend/src/logging/initalize.ts b/backend/src/logging/initalize.ts index 7375aa37..2d3ec44d 100644 --- a/backend/src/logging/initalize.ts +++ b/backend/src/logging/initalize.ts @@ -28,7 +28,7 @@ function initializeLogger(): Logger { level: LOG_LEVEL, json: true, format: format.combine(format.timestamp(), format.json()), - onConnectionError: (err) => { + onConnectionError: (err): void => { // eslint-disable-next-line no-console console.error(`Connection error: ${err}`); }, diff --git a/backend/src/logging/mikroOrmLogger.ts b/backend/src/logging/mikroOrmLogger.ts index 25bbac13..f6907691 100644 --- a/backend/src/logging/mikroOrmLogger.ts +++ b/backend/src/logging/mikroOrmLogger.ts @@ -5,7 +5,7 @@ import { LokiLabels } from 'loki-logger-ts'; export class MikroOrmLogger extends DefaultLogger { private logger: Logger = getLogger(); - log(namespace: LoggerNamespace, message: string, context?: LogContext) { + log(namespace: LoggerNamespace, message: string, context?: LogContext): void { if (!this.isEnabled(namespace, context)) { return; } @@ -48,7 +48,7 @@ export class MikroOrmLogger extends DefaultLogger { } } - private createMessage(namespace: LoggerNamespace, messageArg: string, context?: LogContext) { + private createMessage(namespace: LoggerNamespace, messageArg: string, context?: LogContext): unknown { const labels: LokiLabels = { service: 'ORM', }; diff --git a/backend/src/logging/responseTimeLogger.ts b/backend/src/logging/responseTimeLogger.ts index c1bb1e33..7fcc6c93 100644 --- a/backend/src/logging/responseTimeLogger.ts +++ b/backend/src/logging/responseTimeLogger.ts @@ -1,7 +1,7 @@ import { getLogger, Logger } from './initalize.js'; import { Request, Response } from 'express'; -export function responseTimeLogger(req: Request, res: Response, time: number) { +export function responseTimeLogger(req: Request, res: Response, time: number): void { const logger: Logger = getLogger(); const method = req.method; diff --git a/backend/src/middleware/auth/auth.ts b/backend/src/middleware/auth/auth.ts index 5389dc77..345bfa59 100644 --- a/backend/src/middleware/auth/auth.ts +++ b/backend/src/middleware/auth/auth.ts @@ -1,9 +1,9 @@ import { envVars, getEnvVar } from '../../util/envVars.js'; import { expressjwt } from 'express-jwt'; +import * as jwt from 'jsonwebtoken'; import { JwtPayload } from 'jsonwebtoken'; import jwksClient from 'jwks-rsa'; import * as express from 'express'; -import * as jwt from 'jsonwebtoken'; import { AuthenticatedRequest } from './authenticated-request.js'; import { AuthenticationInfo } from './authentication-info.js'; import { ForbiddenException, UnauthorizedException } from '../../exceptions.js'; @@ -74,7 +74,7 @@ const verifyJwtToken = expressjwt({ */ function getAuthenticationInfo(req: AuthenticatedRequest): AuthenticationInfo | undefined { if (!req.jwtPayload) { - return; + return undefined; } const issuer = req.jwtPayload.iss; let accountType: 'student' | 'teacher'; @@ -84,8 +84,9 @@ function getAuthenticationInfo(req: AuthenticatedRequest): AuthenticationInfo | } else if (issuer === idpConfigs.teacher.issuer) { accountType = 'teacher'; } else { - return; + return undefined; } + return { accountType: accountType, username: req.jwtPayload[JWT_PROPERTY_NAMES.username]!, @@ -100,10 +101,10 @@ function getAuthenticationInfo(req: AuthenticatedRequest): AuthenticationInfo | * Add the AuthenticationInfo object with the information about the current authentication to the request in order * to avoid that the routers have to deal with the JWT token. */ -const addAuthenticationInfo = (req: AuthenticatedRequest, _res: express.Response, next: express.NextFunction) => { +function addAuthenticationInfo(req: AuthenticatedRequest, _res: express.Response, next: express.NextFunction): void { req.auth = getAuthenticationInfo(req); next(); -}; +} export const authenticateUser = [verifyJwtToken, addAuthenticationInfo]; @@ -113,9 +114,8 @@ export const authenticateUser = [verifyJwtToken, addAuthenticationInfo]; * @param accessCondition Predicate over the current AuthenticationInfo. Access is only granted when this evaluates * to true. */ -export const authorize = - (accessCondition: (auth: AuthenticationInfo) => boolean) => - (req: AuthenticatedRequest, _res: express.Response, next: express.NextFunction): void => { +export function authorize(accessCondition: (auth: AuthenticationInfo) => boolean) { + return (req: AuthenticatedRequest, _res: express.Response, next: express.NextFunction): void => { if (!req.auth) { throw new UnauthorizedException(); } else if (!accessCondition(req.auth)) { @@ -124,6 +124,7 @@ export const authorize = next(); } }; +} /** * Middleware which rejects all unauthenticated users, but accepts all authenticated users. diff --git a/backend/src/mikro-orm.config.ts b/backend/src/mikro-orm.config.ts index d53e0398..ffa12c82 100644 --- a/backend/src/mikro-orm.config.ts +++ b/backend/src/mikro-orm.config.ts @@ -54,7 +54,7 @@ function config(testingMode: boolean = false): Options { // Workaround: vitest: `TypeError: Unknown file extension ".ts"` (ERR_UNKNOWN_FILE_EXTENSION) // (see https://mikro-orm.io/docs/guide/project-setup#testing-the-endpoint) - dynamicImportProvider: (id) => import(id), + dynamicImportProvider: async (id) => import(id), }; } diff --git a/backend/src/orm.ts b/backend/src/orm.ts index 8ab5258a..419d5990 100644 --- a/backend/src/orm.ts +++ b/backend/src/orm.ts @@ -4,7 +4,7 @@ import { envVars, getEnvVar } from './util/envVars.js'; import { getLogger, Logger } from './logging/initalize.js'; let orm: MikroORM | undefined; -export async function initORM(testingMode: boolean = false) { +export async function initORM(testingMode: boolean = false): Promise { const logger: Logger = getLogger(); logger.info('Initializing ORM'); diff --git a/backend/src/services/assignments.ts b/backend/src/services/assignments.ts index c637b822..7ac52844 100644 --- a/backend/src/services/assignments.ts +++ b/backend/src/services/assignments.ts @@ -79,7 +79,7 @@ export async function getAssignmentsSubmissions(classid: string, assignmentNumbe const groups = await groupRepository.findAllGroupsForAssignment(assignment); const submissionRepository = getSubmissionRepository(); - const submissions = (await Promise.all(groups.map((group) => submissionRepository.findAllSubmissionsForGroup(group)))).flat(); + const submissions = (await Promise.all(groups.map(async (group) => submissionRepository.findAllSubmissionsForGroup(group)))).flat(); return submissions.map(mapToSubmissionDTO); } diff --git a/backend/src/services/class.ts b/backend/src/services/class.ts index 9f6e1efe..4f3cbc9d 100644 --- a/backend/src/services/class.ts +++ b/backend/src/services/class.ts @@ -24,11 +24,15 @@ export async function getAllClasses(full: boolean): Promise { const teacherRepository = getTeacherRepository(); const teacherUsernames = classData.teachers || []; - const teachers = (await Promise.all(teacherUsernames.map((id) => teacherRepository.findByUsername(id)))).filter((teacher) => teacher != null); + const teachers = (await Promise.all(teacherUsernames.map(async (id) => teacherRepository.findByUsername(id)))).filter( + (teacher) => teacher != null + ); const studentRepository = getStudentRepository(); const studentUsernames = classData.students || []; - const students = (await Promise.all(studentUsernames.map((id) => studentRepository.findByUsername(id)))).filter((student) => student != null); + const students = (await Promise.all(studentUsernames.map(async (id) => studentRepository.findByUsername(id)))).filter( + (student) => student != null + ); //Const cls = mapToClass(classData, teachers, students); diff --git a/backend/src/services/groups.ts b/backend/src/services/groups.ts index ecc92293..6abcd3fc 100644 --- a/backend/src/services/groups.ts +++ b/backend/src/services/groups.ts @@ -43,7 +43,9 @@ export async function createGroup(groupData: GroupDTO, classid: string, assignme const studentRepository = getStudentRepository(); const memberUsernames = (groupData.members as string[]) || []; // TODO check if groupdata.members is a list - const members = (await Promise.all([...memberUsernames].map((id) => studentRepository.findByUsername(id)))).filter((student) => student != null); + const members = (await Promise.all([...memberUsernames].map(async (id) => studentRepository.findByUsername(id)))).filter( + (student) => student != null + ); getLogger().debug(members); diff --git a/backend/src/services/learning-objects/attachment-service.ts b/backend/src/services/learning-objects/attachment-service.ts index aacc7187..4ff4ec47 100644 --- a/backend/src/services/learning-objects/attachment-service.ts +++ b/backend/src/services/learning-objects/attachment-service.ts @@ -3,7 +3,7 @@ import { Attachment } from '../../entities/content/attachment.entity.js'; import { LearningObjectIdentifier } from '../../interfaces/learning-content.js'; const attachmentService = { - getAttachment(learningObjectId: LearningObjectIdentifier, attachmentName: string): Promise { + async getAttachment(learningObjectId: LearningObjectIdentifier, attachmentName: string): Promise { const attachmentRepo = getAttachmentRepository(); if (learningObjectId.version) { diff --git a/backend/src/services/learning-objects/database-learning-object-provider.ts b/backend/src/services/learning-objects/database-learning-object-provider.ts index bab0b9b1..03dbfdff 100644 --- a/backend/src/services/learning-objects/database-learning-object-provider.ts +++ b/backend/src/services/learning-objects/database-learning-object-provider.ts @@ -41,7 +41,7 @@ function convertLearningObject(learningObject: LearningObject | null): FilteredL }; } -function findLearningObjectEntityById(id: LearningObjectIdentifier): Promise { +async function findLearningObjectEntityById(id: LearningObjectIdentifier): Promise { const learningObjectRepo = getLearningObjectRepository(); return learningObjectRepo.findLatestByHruidAndLanguage(id.hruid, id.language as Language); @@ -69,7 +69,7 @@ const databaseLearningObjectProvider: LearningObjectProvider = { if (!learningObject) { return null; } - return await processingService.render(learningObject, (id) => findLearningObjectEntityById(id)); + return await processingService.render(learningObject, async (id) => findLearningObjectEntityById(id)); }, /** @@ -96,7 +96,7 @@ const databaseLearningObjectProvider: LearningObjectProvider = { throw new NotFoundError('The learning path with the given ID could not be found.'); } const learningObjects = await Promise.all( - learningPath.nodes.map((it) => { + learningPath.nodes.map(async (it) => { const learningObject = learningObjectService.getLearningObjectById({ hruid: it.learningObjectHruid, language: it.language, diff --git a/backend/src/services/learning-objects/learning-object-service.ts b/backend/src/services/learning-objects/learning-object-service.ts index 95e5daff..59ffb643 100644 --- a/backend/src/services/learning-objects/learning-object-service.ts +++ b/backend/src/services/learning-objects/learning-object-service.ts @@ -18,28 +18,28 @@ const learningObjectService = { /** * Fetches a single learning object by its HRUID */ - getLearningObjectById(id: LearningObjectIdentifier): Promise { + async getLearningObjectById(id: LearningObjectIdentifier): Promise { return getProvider(id).getLearningObjectById(id); }, /** * Fetch full learning object data (metadata) */ - getLearningObjectsFromPath(id: LearningPathIdentifier): Promise { + async getLearningObjectsFromPath(id: LearningPathIdentifier): Promise { return getProvider(id).getLearningObjectsFromPath(id); }, /** * Fetch only learning object HRUIDs */ - getLearningObjectIdsFromPath(id: LearningPathIdentifier): Promise { + async getLearningObjectIdsFromPath(id: LearningPathIdentifier): Promise { return getProvider(id).getLearningObjectIdsFromPath(id); }, /** * Obtain a HTML-rendering of the learning object with the given identifier (as a string). */ - getLearningObjectHTML(id: LearningObjectIdentifier): Promise { + async getLearningObjectHTML(id: LearningObjectIdentifier): Promise { return getProvider(id).getLearningObjectHTML(id); }, }; diff --git a/backend/src/services/learning-objects/processing/extern/extern-processor.ts b/backend/src/services/learning-objects/processing/extern/extern-processor.ts index 453e998b..162f80d2 100644 --- a/backend/src/services/learning-objects/processing/extern/extern-processor.ts +++ b/backend/src/services/learning-objects/processing/extern/extern-processor.ts @@ -15,7 +15,7 @@ class ExternProcessor extends StringProcessor { super(DwengoContentType.EXTERN); } - override renderFn(externURL: string) { + override renderFn(externURL: string): string { if (!isValidHttpUrl(externURL)) { throw new ProcessingError('The url is not valid: ' + externURL); } diff --git a/backend/src/services/learning-objects/processing/gift/gift-processor.ts b/backend/src/services/learning-objects/processing/gift/gift-processor.ts index 5396236a..8d548f56 100644 --- a/backend/src/services/learning-objects/processing/gift/gift-processor.ts +++ b/backend/src/services/learning-objects/processing/gift/gift-processor.ts @@ -32,7 +32,7 @@ class GiftProcessor extends StringProcessor { super(DwengoContentType.GIFT); } - override renderFn(giftString: string) { + override renderFn(giftString: string): string { const quizQuestions: GIFTQuestion[] = parse(giftString); let html = "
\n"; diff --git a/backend/src/services/learning-objects/processing/image/block-image-processor.ts b/backend/src/services/learning-objects/processing/image/block-image-processor.ts index f4f8a773..6ad427df 100644 --- a/backend/src/services/learning-objects/processing/image/block-image-processor.ts +++ b/backend/src/services/learning-objects/processing/image/block-image-processor.ts @@ -10,7 +10,7 @@ class BlockImageProcessor extends InlineImageProcessor { super(); } - override renderFn(imageUrl: string) { + override renderFn(imageUrl: string): string { const inlineHtml = super.render(imageUrl); return DOMPurify.sanitize(`
${inlineHtml}
`); } diff --git a/backend/src/services/learning-objects/processing/image/inline-image-processor.ts b/backend/src/services/learning-objects/processing/image/inline-image-processor.ts index 478ce326..22e6313e 100644 --- a/backend/src/services/learning-objects/processing/image/inline-image-processor.ts +++ b/backend/src/services/learning-objects/processing/image/inline-image-processor.ts @@ -13,7 +13,7 @@ class InlineImageProcessor extends StringProcessor { super(contentType); } - override renderFn(imageUrl: string) { + override renderFn(imageUrl: string): string { if (!isValidHttpUrl(imageUrl)) { throw new ProcessingError(`Image URL is invalid: ${imageUrl}`); } diff --git a/backend/src/services/learning-objects/processing/markdown/markdown-processor.ts b/backend/src/services/learning-objects/processing/markdown/markdown-processor.ts index 39f2adc8..77673cbf 100644 --- a/backend/src/services/learning-objects/processing/markdown/markdown-processor.ts +++ b/backend/src/services/learning-objects/processing/markdown/markdown-processor.ts @@ -14,7 +14,7 @@ class MarkdownProcessor extends StringProcessor { super(DwengoContentType.TEXT_MARKDOWN); } - override renderFn(mdText: string) { + override renderFn(mdText: string): string { try { marked.use({ renderer: dwengoMarkedRenderer }); const html = marked(mdText, { async: false }); @@ -24,7 +24,7 @@ class MarkdownProcessor extends StringProcessor { } } - replaceLinks(html: string) { + replaceLinks(html: string): string { const proc = new InlineImageProcessor(); html = html.replace( //g, diff --git a/backend/src/services/learning-objects/processing/pdf/pdf-processor.ts b/backend/src/services/learning-objects/processing/pdf/pdf-processor.ts index 26cb4d94..c41de802 100644 --- a/backend/src/services/learning-objects/processing/pdf/pdf-processor.ts +++ b/backend/src/services/learning-objects/processing/pdf/pdf-processor.ts @@ -15,7 +15,7 @@ class PdfProcessor extends StringProcessor { super(DwengoContentType.APPLICATION_PDF); } - override renderFn(pdfUrl: string) { + override renderFn(pdfUrl: string): string { if (!isValidHttpUrl(pdfUrl)) { throw new ProcessingError(`PDF URL is invalid: ${pdfUrl}`); } diff --git a/backend/src/services/learning-objects/processing/processor.ts b/backend/src/services/learning-objects/processing/processor.ts index a11c4416..1dcca255 100644 --- a/backend/src/services/learning-objects/processing/processor.ts +++ b/backend/src/services/learning-objects/processing/processor.ts @@ -9,7 +9,9 @@ import { DwengoContentType } from './content-type.js'; * Based on https://github.com/dwengovzw/Learning-Object-Repository/blob/main/app/processors/processor.js */ abstract class Processor { - protected constructor(public contentType: DwengoContentType) {} + protected constructor(public contentType: DwengoContentType) { + // Do nothing + } /** * Render the given object. diff --git a/backend/src/services/learning-objects/processing/text/text-processor.ts b/backend/src/services/learning-objects/processing/text/text-processor.ts index db6d37df..a2c84150 100644 --- a/backend/src/services/learning-objects/processing/text/text-processor.ts +++ b/backend/src/services/learning-objects/processing/text/text-processor.ts @@ -11,7 +11,7 @@ class TextProcessor extends StringProcessor { super(DwengoContentType.TEXT_PLAIN); } - override renderFn(text: string) { + override renderFn(text: string): string { // Sanitize plain text to prevent xss. return DOMPurify.sanitize(text); } diff --git a/backend/src/services/learning-paths/database-learning-path-provider.ts b/backend/src/services/learning-paths/database-learning-path-provider.ts index bbcb6485..cc12c44c 100644 --- a/backend/src/services/learning-paths/database-learning-path-provider.ts +++ b/backend/src/services/learning-paths/database-learning-path-provider.ts @@ -18,7 +18,7 @@ async function getLearningObjectsForNodes(nodes: LearningPathNode[]): Promise( await Promise.all( - nodes.map((node) => + nodes.map(async (node) => learningObjectService .getLearningObjectById({ hruid: node.learningObjectHruid, @@ -117,7 +117,7 @@ async function convertNodes( nodesToLearningObjects: Map, personalizedFor?: PersonalizationTarget ): Promise { - const nodesPromise = Array.from(nodesToLearningObjects.entries()).map((entry) => + const nodesPromise = Array.from(nodesToLearningObjects.entries()).map(async (entry) => convertNode(entry[0], entry[1], personalizedFor, nodesToLearningObjects) ); return await Promise.all(nodesPromise); @@ -179,11 +179,11 @@ const databaseLearningPathProvider: LearningPathProvider = { ): Promise { const learningPathRepo = getLearningPathRepository(); - const learningPaths = (await Promise.all(hruids.map((hruid) => learningPathRepo.findByHruidAndLanguage(hruid, language)))).filter( + const learningPaths = (await Promise.all(hruids.map(async (hruid) => learningPathRepo.findByHruidAndLanguage(hruid, language)))).filter( (learningPath) => learningPath !== null ); const filteredLearningPaths = await Promise.all( - learningPaths.map((learningPath, index) => convertLearningPath(learningPath, index, personalizedFor)) + learningPaths.map(async (learningPath, index) => convertLearningPath(learningPath, index, personalizedFor)) ); return { @@ -200,7 +200,7 @@ const databaseLearningPathProvider: LearningPathProvider = { const learningPathRepo = getLearningPathRepository(); const searchResults = await learningPathRepo.findByQueryStringAndLanguage(query, language); - return await Promise.all(searchResults.map((result, index) => convertLearningPath(result, index, personalizedFor))); + return await Promise.all(searchResults.map(async (result, index) => convertLearningPath(result, index, personalizedFor))); }, }; diff --git a/backend/src/services/learning-paths/learning-path-service.ts b/backend/src/services/learning-paths/learning-path-service.ts index 4dd21407..f8e328b2 100644 --- a/backend/src/services/learning-paths/learning-path-service.ts +++ b/backend/src/services/learning-paths/learning-path-service.ts @@ -49,7 +49,9 @@ const learningPathService = { * Search learning paths in the data source using the given search string. */ async searchLearningPaths(query: string, language: Language, personalizedFor?: PersonalizationTarget): Promise { - const providerResponses = await Promise.all(allProviders.map((provider) => provider.searchLearningPaths(query, language, personalizedFor))); + const providerResponses = await Promise.all( + allProviders.map(async (provider) => provider.searchLearningPaths(query, language, personalizedFor)) + ); return providerResponses.flat(); }, }; diff --git a/backend/src/services/questions.ts b/backend/src/services/questions.ts index 0433b69f..bb42aabd 100644 --- a/backend/src/services/questions.ts +++ b/backend/src/services/questions.ts @@ -2,7 +2,7 @@ import { getAnswerRepository, getQuestionRepository } from '../data/repositories import { mapToQuestionDTO, mapToQuestionId, QuestionDTO, QuestionId } from '../interfaces/question.js'; import { Question } from '../entities/questions/question.entity.js'; import { Answer } from '../entities/questions/answer.entity.js'; -import { mapToAnswerDTO, mapToAnswerId } from '../interfaces/answer.js'; +import { AnswerDTO, AnswerId, mapToAnswerDTO, mapToAnswerId } from '../interfaces/answer.js'; import { QuestionRepository } from '../data/questions/question-repository.js'; import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; import { mapToStudent } from '../interfaces/student.js'; @@ -45,7 +45,7 @@ export async function getQuestion(questionId: QuestionId): Promise { const answerRepository = getAnswerRepository(); const question = await fetchQuestion(questionId); @@ -68,7 +68,7 @@ export async function getAnswersByQuestion(questionId: QuestionId, full: boolean return answersDTO.map(mapToAnswerId); } -export async function createQuestion(questionDTO: QuestionDTO) { +export async function createQuestion(questionDTO: QuestionDTO): Promise { const questionRepository = getQuestionRepository(); const author = mapToStudent(questionDTO.author); @@ -86,7 +86,7 @@ export async function createQuestion(questionDTO: QuestionDTO) { return questionDTO; } -export async function deleteQuestion(questionId: QuestionId) { +export async function deleteQuestion(questionId: QuestionId): Promise { const questionRepository = getQuestionRepository(); const question = await fetchQuestion(questionId); diff --git a/backend/src/services/submissions.ts b/backend/src/services/submissions.ts index 153ce169..b47e04bf 100644 --- a/backend/src/services/submissions.ts +++ b/backend/src/services/submissions.ts @@ -2,6 +2,7 @@ import { getSubmissionRepository } from '../data/repositories.js'; import { Language } from '../entities/content/language.js'; import { LearningObjectIdentifier } from '../entities/content/learning-object-identifier.js'; import { mapToSubmission, mapToSubmissionDTO, SubmissionDTO } from '../interfaces/submission.js'; +import { Submission } from '../entities/assignments/submission.entity.js'; export async function getSubmission( learningObjectHruid: string, @@ -21,7 +22,7 @@ export async function getSubmission( return mapToSubmissionDTO(submission); } -export async function createSubmission(submissionDTO: SubmissionDTO) { +export async function createSubmission(submissionDTO: SubmissionDTO): Promise { const submissionRepository = getSubmissionRepository(); const submission = mapToSubmission(submissionDTO); @@ -35,7 +36,12 @@ export async function createSubmission(submissionDTO: SubmissionDTO) { return submission; } -export async function deleteSubmission(learningObjectHruid: string, language: Language, version: number, submissionNumber: number) { +export async function deleteSubmission( + learningObjectHruid: string, + language: Language, + version: number, + submissionNumber: number +): Promise { const submissionRepository = getSubmissionRepository(); const submission = getSubmission(learningObjectHruid, language, version, submissionNumber); diff --git a/backend/src/services/teachers.ts b/backend/src/services/teachers.ts index 1949152f..1b098778 100644 --- a/backend/src/services/teachers.ts +++ b/backend/src/services/teachers.ts @@ -77,7 +77,7 @@ export async function getClassIdsByTeacher(username: string): Promise return classes.map((cls) => cls.id); } -export async function fetchStudentsByTeacher(username: string) { +export async function fetchStudentsByTeacher(username: string): Promise { const classes = await getClassIdsByTeacher(username); return (await Promise.all(classes.map(async (id) => getClassStudents(id)))).flat(); diff --git a/backend/src/util/async.ts b/backend/src/util/async.ts index a5fc9b82..7b7b8818 100644 --- a/backend/src/util/async.ts +++ b/backend/src/util/async.ts @@ -6,7 +6,11 @@ * @param regex * @param replacementFn */ -export async function replaceAsync(str: string, regex: RegExp, replacementFn: (match: string, ...args: string[]) => Promise) { +export async function replaceAsync( + str: string, + regex: RegExp, + replacementFn: (match: string, ...args: string[]) => Promise +): Promise { const promises: Promise[] = []; // First run through matches: add all Promises resulting from the replacement function diff --git a/backend/src/util/links.ts b/backend/src/util/links.ts index c4b54c72..ff334eb5 100644 --- a/backend/src/util/links.ts +++ b/backend/src/util/links.ts @@ -9,7 +9,7 @@ export function isValidHttpUrl(url: string): boolean { } } -export function getUrlStringForLearningObject(learningObjectId: LearningObjectIdentifier) { +export function getUrlStringForLearningObject(learningObjectId: LearningObjectIdentifier): string { let url = `/learningObject/${learningObjectId.hruid}/html?language=${learningObjectId.language}`; if (learningObjectId.version) { url += `&version=${learningObjectId.version}`; diff --git a/backend/tests/services/learning-objects/database-learning-object-provider.test.ts b/backend/tests/services/learning-objects/database-learning-object-provider.test.ts index 4750e4bd..2c3b7dfc 100644 --- a/backend/tests/services/learning-objects/database-learning-object-provider.test.ts +++ b/backend/tests/services/learning-objects/database-learning-object-provider.test.ts @@ -78,7 +78,7 @@ describe('DatabaseLearningObjectProvider', () => { }); it('should throw an error if queried with a path identifier for which there is no learning path', async () => { await expect( - (async () => { + (async (): Promise => { await databaseLearningObjectProvider.getLearningObjectIdsFromPath({ hruid: 'non_existing_hruid', language: Language.Dutch, @@ -97,7 +97,7 @@ describe('DatabaseLearningObjectProvider', () => { }); it('should throw an error if queried with a path identifier for which there is no learning path', async () => { await expect( - (async () => { + (async (): Promise => { await databaseLearningObjectProvider.getLearningObjectsFromPath({ hruid: 'non_existing_hruid', language: Language.Dutch, diff --git a/backend/tests/services/learning-path/database-learning-path-provider.test.ts b/backend/tests/services/learning-path/database-learning-path-provider.test.ts index 04782df3..8d9dd530 100644 --- a/backend/tests/services/learning-path/database-learning-path-provider.test.ts +++ b/backend/tests/services/learning-path/database-learning-path-provider.test.ts @@ -124,7 +124,7 @@ describe('DatabaseLearningPathProvider', () => { const learningObjectsOnPath = ( await Promise.all( - example.learningPath.nodes.map((node) => + example.learningPath.nodes.map(async (node) => learningObjectService.getLearningObjectById({ hruid: node.learningObjectHruid, version: node.version, diff --git a/backend/tests/setup-tests.ts b/backend/tests/setup-tests.ts index 9502bcb8..016099f3 100644 --- a/backend/tests/setup-tests.ts +++ b/backend/tests/setup-tests.ts @@ -14,7 +14,7 @@ import { makeTestQuestions } from './test_assets/questions/questions.testdata.js import { makeTestAnswers } from './test_assets/questions/answers.testdata.js'; import { makeTestSubmissions } from './test_assets/assignments/submission.testdata.js'; -export async function setupTestApp() { +export async function setupTestApp(): Promise { dotenv.config({ path: '.env.test' }); await initORM(true); diff --git a/backend/tests/test-assets/learning-objects/dummy/dummy-learning-object-example.ts b/backend/tests/test-assets/learning-objects/dummy/dummy-learning-object-example.ts index b1bd3089..f810d57a 100644 --- a/backend/tests/test-assets/learning-objects/dummy/dummy-learning-object-example.ts +++ b/backend/tests/test-assets/learning-objects/dummy/dummy-learning-object-example.ts @@ -11,7 +11,7 @@ import { envVars, getEnvVar } from '../../../../src/util/envVars'; */ export function dummyLearningObject(hruid: string, language: Language, title: string): LearningObjectExample { return { - createLearningObject: () => { + createLearningObject: (): LearningObject => { const learningObject = new LearningObject(); learningObject.hruid = getEnvVar(envVars.UserContentPrefix) + hruid; learningObject.language = language; diff --git a/backend/tests/test-assets/learning-paths/learning-path-utils.ts b/backend/tests/test-assets/learning-paths/learning-path-utils.ts index c567de66..eb786fe1 100644 --- a/backend/tests/test-assets/learning-paths/learning-path-utils.ts +++ b/backend/tests/test-assets/learning-paths/learning-path-utils.ts @@ -3,7 +3,12 @@ import { LearningPathTransition } from '../../../src/entities/content/learning-p import { LearningPathNode } from '../../../src/entities/content/learning-path-node.entity'; import { LearningPath } from '../../../src/entities/content/learning-path.entity'; -export function createLearningPathTransition(node: LearningPathNode, transitionNumber: number, condition: string | null, to: LearningPathNode) { +export function createLearningPathTransition( + node: LearningPathNode, + transitionNumber: number, + condition: string | null, + to: LearningPathNode +): LearningPathTransition { const trans = new LearningPathTransition(); trans.node = node; trans.transitionNumber = transitionNumber; @@ -19,7 +24,7 @@ export function createLearningPathNode( version: number, language: Language, startNode: boolean -) { +): LearningPathNode { const node = new LearningPathNode(); node.learningPath = learningPath; node.nodeNumber = nodeNumber; diff --git a/backend/tests/test-utils/expectations.ts b/backend/tests/test-utils/expectations.ts index 0fe63811..347f4b40 100644 --- a/backend/tests/test-utils/expectations.ts +++ b/backend/tests/test-utils/expectations.ts @@ -69,7 +69,7 @@ export function expectToBeCorrectEntity(actual: { entity: T; n * @param filtered the representation as FilteredLearningObject * @param original the original entity added to the database */ -export function expectToBeCorrectFilteredLearningObject(filtered: FilteredLearningObject, original: LearningObject) { +export function expectToBeCorrectFilteredLearningObject(filtered: FilteredLearningObject, original: LearningObject): void { expect(filtered.uuid).toEqual(original.uuid); expect(filtered.version).toEqual(original.version); expect(filtered.language).toEqual(original.language); @@ -105,7 +105,7 @@ export function expectToBeCorrectLearningPath( learningPath: LearningPath, expectedEntity: LearningPathEntity, learningObjectsOnPath: FilteredLearningObject[] -) { +): void { expect(learningPath.hruid).toEqual(expectedEntity.hruid); expect(learningPath.language).toEqual(expectedEntity.language); expect(learningPath.description).toEqual(expectedEntity.description); diff --git a/eslint.config.ts b/eslint.config.ts index e4534398..3596633a 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -23,11 +23,20 @@ export default [ languageOptions: { ecmaVersion: 'latest', sourceType: 'module', + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, }, linterOptions: { reportUnusedInlineConfigs: 'error', }, rules: { + 'consistent-return': 'off', + '@typescript-eslint/consistent-return': 'off', + + '@typescript-eslint/explicit-function-return-type': 'warn', + '@typescript-eslint/naming-convention': [ 'warn', { // Enforce that all variables, functions and properties are camelCase @@ -49,6 +58,14 @@ export default [ } ], + // 'no-empty-function': 'off', + '@typescript-eslint/no-empty-function': 'error', + + 'no-loop-func': 'off', + '@typescript-eslint/no-loop-func': 'error', + + '@typescript-eslint/no-unsafe-function-type': 'error', + 'no-unused-expressions': 'off', '@typescript-eslint/no-unused-expressions': 'warn', 'no-unused-vars': 'off', @@ -66,6 +83,10 @@ export default [ 'no-use-before-define': 'off', '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/prefer-function-type': 'error', + + '@typescript-eslint/promise-function-async': 'warn', + 'no-await-in-loop': 'warn', 'no-constructor-return': 'error', 'no-duplicate-imports': 'error', @@ -110,7 +131,6 @@ export default [ 'no-iterator': 'error', 'no-label-var': 'warn', 'no-labels': 'warn', - 'no-loop-func': 'error', 'no-multi-assign': 'error', 'no-nested-ternary': 'error', 'no-object-constructor': 'error',