NewsletterCreator / src / utils / checkNewsletter.js
checkNewsletter.js
Raw
import { useSettingsStore } from 'src/stores/settings.js'
import translation from 'src/i18n'

export default function checkNewsletter (newsletter, elements) {
  /*
      * checks:
      * - newsletter has title, creationTime, CreatorVersion and sections
      * - newsletter version is not newer than the current version
      * - each section has a valid name (meaning has available translation)
      * - each element of the section has a valid type (meaning type is defined in elements) and valid data (meaning data is in the correct format ignoring strings and arrays)
      */

  // check if newsletter has title, creationTime, CreatorVersion and sections
  if (newsletter.title === undefined || newsletter.creationTime === undefined || newsletter.CreatorVersion === undefined || newsletter.sections === undefined) {
    throw new Error('Newsletter has invalid format: missing title, creationTime, CreatorVersion or sections')
  }

  // check if newsletter version is not newer than the current version
  const version = useSettingsStore().appVersion
  if (newsletter.CreatorVersion > version) {
    throw new Error('Newsletter has invalid format: CreatorVersion is newer than the current version')
  }

  // check if each section has a valid name by checking if a translation for the section name exists
  // therefore to add custom section names, add them to the i18n translation
  newsletter.sections.forEach(section => {
    const sectionName = section.name
    for (const lang in translation) {
      if (!(sectionName in translation[lang].section)) {
        throw new Error(`Newsletter has invalid format: section name ${sectionName} is not valid`)
      }
    }
  })

  // check if each element of the section has a valid type and data
  newsletter.sections.forEach(section => {
    section.elements.forEach(element => {
      // checking type
      if (!elements[element.type]) {
        throw new Error(`Newsletter has invalid format: element type ${element.type} is not valid`)
      }
      // checking if data is structurally the same as in element definition
      const elementData = element.data
      const expectedData = elements[element.type].data
      const keysElementData = Object.keys(elementData)
      const keysExpectedData = Object.keys(expectedData)

      for (const key of keysElementData) {
        if (!keysExpectedData.includes(key)) {
          throw new Error(`Newsletter has invalid format: element data for type ${element.type} is not valid`)
        }

        // recursively checking deeper keys of object
        if (typeof elementData[key] === 'object' && typeof expectedData[key] === 'object') {
          const subKeysElementData = Object.keys(elementData[key])
          const subKeysExpectedData = Object.keys(expectedData[key])

          if (subKeysElementData.length !== subKeysExpectedData.length) {
            throw new Error(`Newsletter has invalid format: element data for type ${element.type} is not valid`)
          }

          for (const subKey of subKeysElementData) {
            if (!subKeysExpectedData.includes(subKey) || typeof elementData[key][subKey] !== typeof expectedData[key][subKey]) {
              throw new Error(`Newsletter has invalid format: element data for type ${element.type} is not valid`)
            }
          }
        } else if (typeof elementData[key] !== typeof expectedData[key]) {
          throw new Error(`Newsletter has invalid format: element data for type ${element.type} is not valid`)
        }
      }
    })
  })
}