Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build process should fail if agendabasel.ch API fails #186

Closed
maehr opened this issue Sep 6, 2024 · 1 comment
Closed

Build process should fail if agendabasel.ch API fails #186

maehr opened this issue Sep 6, 2024 · 1 comment
Assignees
Labels
enhancement New feature or request

Comments

@maehr
Copy link
Member

maehr commented Sep 6, 2024

Describe what feature you'd like. Pseudo-code, mockups, or screenshots of similar solutions are encouraged!

To ensure that the build process fails if agendabasel.ch is not reachable or if the returned data is empty, you can modify the getActivities function to throw an error in these cases. This will cause the build process to fail when running in production mode, as the error will propagate and stop the build.

Here's how you can modify the getActivities function:

  1. Check if the response from fetch is successful: If the fetch request fails (e.g., due to a network issue or a server error), throw an error.
  2. Check if the response body is empty: If the fetched data is empty, throw an error.
  3. Handle build process interruption: In production mode (i.e., when dev is false), the error should cause the build process to fail.

Modified getActivities Function

async function getActivities() {
	try {
		// Fetch the XML export from the external URL
		const response = await fetch('https://agendabasel.ch/xmlexport/kzexport-basel.xml');

		// Check if the response is OK (status 200-299)
		if (!response.ok) {
			throw new Error(`Failed to fetch data: ${response.statusText}`);
		}

		// Parse the response as text
		const xml = await response.text();

		// Check if the response is empty
		if (!xml) {
			throw new Error('Received empty response from the server.');
		}

		// Parse the XML into a JavaScript object
		const data = await parseStringPromise(xml);

		// Extract activities
		const activities = data['kdz:exportActivities']['Activities'][0]['Activity'];

		// If activities array is empty, throw an error
		if (!activities || activities.length === 0) {
			throw new Error('No activities found in the response.');
		}

		// Save data to a file in dev mode
		if (dev) {
			await saveToFile(activities, join(tmpdir(), 'activities.json'));
			console.log(getUniqueOwners(activities));
		}

		// Filter and parse the activities based on configured partners
		const partners = config.partners;

		const parsedActivities = activities
			.filter(({ $: { owner } }) => partners.includes(owner))
			.map(
				({
					$: { owner, dauerausstellung },
					Title: [title],
					ShortDescription: [shortDesc],
					LongDescription: [longDesc],
					OriginURL: [originUrl],
					ActivityDates: [{ ActivityDate: dates = [] } = {}]
				}) => ({
					owner,
					dauerausstellung,
					title,
					shortDescription: DOMPurify.sanitize(shortDesc, { ALLOWED_TAGS: [] }),
					longDescription: DOMPurify.sanitize(longDesc, { ALLOWED_TAGS: [] }),
					originUrl,
					dates: dates.map(
						({ $: { startDate, endDate, startTime, endTime }, TicketURL: [ticketURL] }) => ({
							startDate,
							endDate,
							startTime,
							endTime,
							ticketURL: ticketURL
						})
					)
				})
			);

		const exhibitions = parsedActivities
			.filter(({ dauerausstellung }) => dauerausstellung === '1')
			.sort((a, b) => a.owner.localeCompare(b.owner));
		const events = parsedActivities.filter(({ dauerausstellung }) => dauerausstellung === '0');

		const flatEvents = events
			.flatMap(({ dates, owner, title, shortDescription, originUrl }) =>
				dates.map((date) => ({ ...date, owner, title, shortDescription, originUrl }))
			)
			.sort((a, b) => new Date(a.startDate).getTime() - new Date(b.startDate).getTime());

		return { events: flatEvents, exhibitions };

	} catch (error) {
		// In production, throw an error to stop the build process
		if (!dev) {
			throw new Error(`Error fetching activities: ${error.message}`);
		} else {
			console.error(error);
			return { events: [], exhibitions: [] };  // Return empty arrays in dev mode for testing
		}
	}
}

Key Changes:

  • Fetch Error Handling: If fetch fails (e.g., the server is unreachable), it throws an error.
  • Empty Response Handling: If the response is empty or if there are no activities in the XML, it throws an error.
  • Production Mode Build Fail: If dev is false, an error will be thrown, which will cause the build to fail.
  • Development Mode: In dev mode, the error is logged to the console, but it won't interrupt the process, allowing testing and debugging.

With this setup, the build process will halt with an error if the external resource is unreachable or the data is invalid, ensuring that the application doesn't proceed with incomplete or missing data.

What type of pull request would this be?

Enhancement

Any links to similar examples or other references we should review?

@maehr maehr added the enhancement New feature or request label Sep 6, 2024
@koilebeit
Copy link
Contributor

fixed by #189

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants