Merge remote-tracking branch 'origin/dev' into feature/own-learning-objects

# Conflicts:
#	backend/package.json
#	backend/src/config.ts
#	backend/src/controllers/learningObjects.ts
#	backend/src/controllers/learningPaths.ts
#	backend/src/data/content/attachment-repository.ts
#	backend/src/data/content/learning-object-repository.ts
#	backend/src/data/content/learning-path-repository.ts
#	backend/src/data/repositories.ts
#	backend/src/entities/content/learning-path.entity.ts
#	backend/src/exceptions.ts
#	backend/src/routes/learning-objects.ts
#	backend/src/services/learningObjects.ts
#	backend/src/services/learningPaths.ts
#	backend/src/util/apiHelper.ts
#	backend/src/util/envvars.ts
#	package-lock.json
This commit is contained in:
Gerald Schmittinger 2025-03-11 03:01:18 +01:00
commit cd0a3a8a7b
119 changed files with 8837 additions and 1697 deletions

View file

@ -1,6 +1,7 @@
import axios, { AxiosRequestConfig } from 'axios';
import { getLogger, Logger } from '../logging/initalize.js';
// !!!! when logger is done -> change
const logger: Logger = getLogger();
/**
* Utility function to fetch data from an API endpoint with error handling.
@ -28,19 +29,14 @@ export async function fetchWithLogging<T>(
} catch (error: any) {
if (error.response) {
if (error.response.status === 404) {
console.error(
`❌ ERROR: ${description} not found (404) at "${url}".`
);
logger.debug(`❌ ERROR: ${description} not found (404) at "${url}".`);
} else {
console.error(
logger.debug(
`❌ ERROR: Failed to fetch ${description}. Status: ${error.response.status} - ${error.response.statusText} (URL: "${url}")`
);
}
} else {
console.error(
`❌ ERROR: Network or unexpected error when fetching ${description}:`,
error.message
);
logger.debug(`❌ ERROR: Network or unexpected error when fetching ${description}:`, error.message);
}
return null;
}

View file

@ -1,5 +1,9 @@
const PREFIX = 'DWENGO_';
const DB_PREFIX = PREFIX + 'DB_';
const IDP_PREFIX = PREFIX + 'AUTH_';
const STUDENT_IDP_PREFIX = IDP_PREFIX + 'STUDENT_';
const TEACHER_IDP_PREFIX = IDP_PREFIX + 'TEACHER_';
const CORS_PREFIX = PREFIX + 'CORS_';
type EnvVar = { key: string; required?: boolean; defaultValue?: any };
@ -14,6 +18,15 @@ export const EnvVars: { [key: string]: EnvVar } = {
LearningContentRepoApiBaseUrl: { key: PREFIX + "LEARNING_CONTENT_REPO_API_BASE_URL", defaultValue: "https://dwengo.org/backend/api"},
FallbackLanguage: { key: PREFIX + "FALLBACK_LANGUAGE", defaultValue: "nl" },
UserContentPrefix: { key: DB_PREFIX + 'USER_CONTENT_PREFIX', defaultValue: "u_" },
IdpStudentUrl: { key: STUDENT_IDP_PREFIX + 'URL', required: true },
IdpStudentClientId: { key: STUDENT_IDP_PREFIX + 'CLIENT_ID', required: true },
IdpStudentJwksEndpoint: { key: STUDENT_IDP_PREFIX + 'JWKS_ENDPOINT', required: true },
IdpTeacherUrl: { key: TEACHER_IDP_PREFIX + 'URL', required: true },
IdpTeacherClientId: { key: TEACHER_IDP_PREFIX + 'CLIENT_ID', required: true },
IdpTeacherJwksEndpoint: { key: TEACHER_IDP_PREFIX + 'JWKS_ENDPOINT', required: true },
IdpAudience: { key: IDP_PREFIX + 'AUDIENCE', defaultValue: 'account' },
CorsAllowedOrigins: { key: CORS_PREFIX + 'ALLOWED_ORIGINS', defaultValue: '' },
CorsAllowedHeaders: { key: CORS_PREFIX + 'ALLOWED_HEADERS', defaultValue: 'Authorization,Content-Type' },
} as const;
/**
@ -39,9 +52,7 @@ export function getNumericEnvVar(envVar: EnvVar): number {
const valueString = getEnvVar(envVar);
const value = parseInt(valueString);
if (isNaN(value)) {
throw new Error(
`Invalid value for environment variable ${envVar.key}: ${valueString}. Expected a number.`
);
throw new Error(`Invalid value for environment variable ${envVar.key}: ${valueString}. Expected a number.`);
} else {
return value;
}

View file

@ -1,7 +1,10 @@
import fs from 'fs';
import path from 'path';
import yaml from 'js-yaml';
import {FALLBACK_LANG} from "../../config";
import { FALLBACK_LANG } from '../config.js';
import { getLogger, Logger } from '../logging/initalize.js';
const logger: Logger = getLogger();
export function loadTranslations<T>(language: string): T {
try {
@ -9,10 +12,7 @@ export function loadTranslations<T>(language: string): T {
const yamlFile = fs.readFileSync(filePath, 'utf8');
return yaml.load(yamlFile) as T;
} catch (error) {
console.error(
`Cannot load translation for ${language}, fallen back to dutch`
);
console.error(error);
logger.warn(`Cannot load translation for ${language}, fallen back to dutch`, error);
const fallbackPath = path.join(process.cwd(), '_i18n', `${FALLBACK_LANG}.yml`);
return yaml.load(fs.readFileSync(fallbackPath, 'utf8')) as T;
}