refactor(backend): Functions

This commit is contained in:
Tibo De Peuter 2025-03-22 18:38:38 +01:00
parent 5ec62554e3
commit 65c1a5e6b6
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
57 changed files with 172 additions and 117 deletions

View file

@ -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<Attachment | null> {
async getAttachment(learningObjectId: LearningObjectIdentifier, attachmentName: string): Promise<Attachment | null> {
const attachmentRepo = getAttachmentRepository();
if (learningObjectId.version) {

View file

@ -41,7 +41,7 @@ function convertLearningObject(learningObject: LearningObject | null): FilteredL
};
}
function findLearningObjectEntityById(id: LearningObjectIdentifier): Promise<LearningObject | null> {
async function findLearningObjectEntityById(id: LearningObjectIdentifier): Promise<LearningObject | null> {
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,

View file

@ -18,28 +18,28 @@ const learningObjectService = {
/**
* Fetches a single learning object by its HRUID
*/
getLearningObjectById(id: LearningObjectIdentifier): Promise<FilteredLearningObject | null> {
async getLearningObjectById(id: LearningObjectIdentifier): Promise<FilteredLearningObject | null> {
return getProvider(id).getLearningObjectById(id);
},
/**
* Fetch full learning object data (metadata)
*/
getLearningObjectsFromPath(id: LearningPathIdentifier): Promise<FilteredLearningObject[]> {
async getLearningObjectsFromPath(id: LearningPathIdentifier): Promise<FilteredLearningObject[]> {
return getProvider(id).getLearningObjectsFromPath(id);
},
/**
* Fetch only learning object HRUIDs
*/
getLearningObjectIdsFromPath(id: LearningPathIdentifier): Promise<string[]> {
async getLearningObjectIdsFromPath(id: LearningPathIdentifier): Promise<string[]> {
return getProvider(id).getLearningObjectIdsFromPath(id);
},
/**
* Obtain a HTML-rendering of the learning object with the given identifier (as a string).
*/
getLearningObjectHTML(id: LearningObjectIdentifier): Promise<string | null> {
async getLearningObjectHTML(id: LearningObjectIdentifier): Promise<string | null> {
return getProvider(id).getLearningObjectHTML(id);
},
};

View file

@ -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);
}

View file

@ -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 = "<div class='learning-object-gift'>\n";

View file

@ -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(`<div>${inlineHtml}</div>`);
}

View file

@ -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}`);
}

View file

@ -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(
/<img.*?src="(.*?)".*?(alt="(.*?)")?.*?(title="(.*?)")?.*?>/g,

View file

@ -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}`);
}

View file

@ -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<T> {
protected constructor(public contentType: DwengoContentType) {}
protected constructor(public contentType: DwengoContentType) {
// Do nothing
}
/**
* Render the given object.

View file

@ -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);
}