Tietokilta / ilmomasiina

Event signup system for tietokilta.fi and beyond
MIT License
1 stars 9 forks source link

Cleaner solution for the flattening of ORM object to plain objects after database fetches #100

Open Jaakkonen opened 1 year ago

Jaakkonen commented 1 year ago

Currently the database queries are done using ORM and then converting the database response to a normal Javascript object via doing countless maps and _.get({plain:true}) calls.

This often leads to problems that are hard to notice. For example the following code from fetching event details as an admin produces responses not matching the schema:

# packages/ilmomasiina-backend/src/routes/events/getEventDetails.ts
# ...
  return stringifyDates({
    ...event.get({ plain: true }),
    questions: event.questions!.map((question) => ({
      ...question.get({ plain: true }),
      // Split answer options into array
      // TODO: Splitting by semicolon might cause problems - requires better solution
      options: question.options ? question.options.split(';') : null,
    })),
    updatedAt: event.updatedAt,
    quotas: event.quotas!.map((quota) => ({
      ...quota.get({ plain: true }),
      signups: quota.signups!.map((signup) => ({
        ...signup.get({ plain: true }),
        status: signup.status,
        answers: signup.answers!,
        confirmed: Boolean(signup.confirmedAt),
      })),
      signupCount: quota.signups!.length,
    })),
  });

The problem here is that the signup.answers! is actually a foreign key lookup and the items of that answers! array are still the ORM wrapped objects.
The fix is quite simple:

answers: signup.answers!.map((answer) => answer.get({ plain: true })),

The problem still remains quite annoying and I see it making it harder to onboard people to the project and takes quite some skill to figure out what's wrong here since with the current setup the schema validation only gives the last nested field name in the error message and not the full path to the point in JSON where the data was invalid :D