fix: api helper voor extra error checks bij fetch dwengo api + schrijffout in controllers/themes
This commit is contained in:
		
							parent
							
								
									0c7f5791ea
								
							
						
					
					
						commit
						91eb374b7e
					
				
					 5 changed files with 45 additions and 8 deletions
				
			
		|  | @ -17,7 +17,7 @@ function loadTranslations(language: string): Translations { | ||||||
|         return yaml.load(yamlFile) as Translations; |         return yaml.load(yamlFile) as Translations; | ||||||
|     } catch (error) { |     } catch (error) { | ||||||
|         console.error( |         console.error( | ||||||
|             `Cant load for language: ${language}, fallen back on dutch` |             `Cannot load translation for: ${language}, fallen back to Dutch` | ||||||
|         ); |         ); | ||||||
|         console.error(error); |         console.error(error); | ||||||
|         const fallbackPath = path.join(process.cwd(), '_i18n', 'nl.yml'); |         const fallbackPath = path.join(process.cwd(), '_i18n', 'nl.yml'); | ||||||
|  |  | ||||||
|  | @ -3,9 +3,12 @@ import { getAllLearningObjects } from '../controllers/learningObjects.js'; | ||||||
| 
 | 
 | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
| 
 | 
 | ||||||
|  | // DWENGO learning objects
 | ||||||
|  | 
 | ||||||
| // Arg: hruid learningPath
 | // Arg: hruid learningPath
 | ||||||
| // Query: language
 | // Query: language
 | ||||||
| // Route to fetch list of learning objects based on hruid of learning path
 | // Route to fetch list of learning objects based on hruid of learning path
 | ||||||
|  | // example: http://localhost:3000/learningObject/un_artificiele_intelligentie
 | ||||||
| router.get('/:hruid', getAllLearningObjects); | router.get('/:hruid', getAllLearningObjects); | ||||||
| 
 | 
 | ||||||
| export default router; | export default router; | ||||||
|  |  | ||||||
|  | @ -8,6 +8,8 @@ import { | ||||||
| 
 | 
 | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
| 
 | 
 | ||||||
|  | // DWENGO learning paths
 | ||||||
|  | 
 | ||||||
| // Query: hruids(list), language
 | // Query: hruids(list), language
 | ||||||
| // Route to fetch learning paths based on a list of HRUIDs
 | // Route to fetch learning paths based on a list of HRUIDs
 | ||||||
| // Example: http://localhost:3000/learningPath?hruids=pn_werking&hruids=art1
 | // Example: http://localhost:3000/learningPath?hruids=pn_werking&hruids=art1
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| import axios from 'axios'; | import axios from 'axios'; | ||||||
| import { DWENGO_API_BASE } from '../config/config.js'; | import { DWENGO_API_BASE } from '../config/config.js'; | ||||||
|  | import { fetchWithLogging } from "../util/apiHelper.js"; | ||||||
| 
 | 
 | ||||||
| interface LearningObjectNode { | interface LearningObjectNode { | ||||||
|     _id: string; |     _id: string; | ||||||
|  | @ -18,7 +19,7 @@ function filterLearningObjectMetadata(data: any, htmlUrl: string) { | ||||||
| 
 | 
 | ||||||
|         title: data.title, |         title: data.title, | ||||||
|         htmlUrl, |         htmlUrl, | ||||||
|         // Html content object
 |         // Url to fetch html content
 | ||||||
|         language: data.language, |         language: data.language, | ||||||
|         difficulty: data.difficulty, |         difficulty: data.difficulty, | ||||||
|         estimatedTime: data.estimated_time, |         estimatedTime: data.estimated_time, | ||||||
|  | @ -50,15 +51,18 @@ export async function getLearningObjectsFromPath( | ||||||
| ) { | ) { | ||||||
|     try { |     try { | ||||||
|         const learningPathUrl = `${DWENGO_API_BASE}/learningPath/${hruid}/${language}`; |         const learningPathUrl = `${DWENGO_API_BASE}/learningPath/${hruid}/${language}`; | ||||||
|         const learningPathResponse = await axios.get(learningPathUrl); |         const learningPathData = await fetchWithLogging<{ nodes: LearningObjectNode[] }>( | ||||||
|         const nodes = learningPathResponse.data.nodes; |             learningPathUrl, | ||||||
|  |             `Learning path for HRUID "${hruid}" in language "${language}"` | ||||||
|  |         ); | ||||||
| 
 | 
 | ||||||
|         if (!nodes || nodes.length === 0) { |         if (!learningPathData || !learningPathData.nodes || learningPathData.nodes.length === 0) { | ||||||
|             throw new Error('No learning objects found in this learning path.'); |             console.error(`⚠️ WARNING: Learning path "${hruid}" exists but contains no learning objects.`); | ||||||
|  |             return []; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return await Promise.all( |         return await Promise.all( | ||||||
|             nodes.map(async (node: LearningObjectNode) => { |             learningPathData.nodes.map(async (node: LearningObjectNode) => { | ||||||
|                 const metadataUrl = `${DWENGO_API_BASE}/learningObject/getMetadata?hruid=${node.learningobject_hruid}&version=${node.version}&language=${language}`; |                 const metadataUrl = `${DWENGO_API_BASE}/learningObject/getMetadata?hruid=${node.learningobject_hruid}&version=${node.version}&language=${language}`; | ||||||
|                 const metadataResponse = await axios.get(metadataUrl); |                 const metadataResponse = await axios.get(metadataUrl); | ||||||
| 
 | 
 | ||||||
|  | @ -72,6 +76,5 @@ export async function getLearningObjectsFromPath( | ||||||
|         ); |         ); | ||||||
|     } catch (error) { |     } catch (error) { | ||||||
|         console.error('Error fetching learning objects:', error); |         console.error('Error fetching learning objects:', error); | ||||||
|         throw new Error('Failed to fetch learning objects.'); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								backend/src/util/apiHelper.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								backend/src/util/apiHelper.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | ||||||
|  | import axios from 'axios'; | ||||||
|  | 
 | ||||||
|  | // !!!! when logger is done -> change
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Utility function to fetch data from an API endpoint with error handling. | ||||||
|  |  * Logs errors but does NOT throw exceptions to keep the system running. | ||||||
|  |  * | ||||||
|  |  * @param url The API endpoint to fetch from. | ||||||
|  |  * @param description A short description of what is being fetched (for logging). | ||||||
|  |  * @returns The response data if successful, or null if an error occurs. | ||||||
|  |  */ | ||||||
|  | export async function fetchWithLogging<T>(url: string, description: string): Promise<T | null> { | ||||||
|  |     try { | ||||||
|  |         const response = await axios.get<T>(url); | ||||||
|  |         return response.data; | ||||||
|  |     } catch (error: any) { | ||||||
|  |         if (error.response) { | ||||||
|  |             if (error.response.status === 404) { | ||||||
|  |                 console.error(`❌ ERROR: ${description} not found (404) at "${url}".`); | ||||||
|  |             } else { | ||||||
|  |                 console.error(`❌ 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); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in a new issue
	
	 Gabriellvl
						Gabriellvl