async function fetchContent({ syncToken, pluginConfig, reporter }) {
  // Fetch locales and check connectivity
  const contentfulClientOptions = createContentfulClientOptions({
    pluginConfig,
    reporter,
  })
  const client = createClient(contentfulClientOptions)

  // The sync API puts the locale in all fields in this format { fieldName:
  // {'locale': value} } so we need to get the space and its default local.
  let space
  let locales
  let defaultLocale = `en-US`
  try {
    reporter.verbose(`Fetching default locale`)
    space = await client.getSpace()
    locales = await client.getLocales().then(response => response.items)
    defaultLocale = _.find(locales, { default: true }).code
    reporter.verbose(
      `Default locale is: ${defaultLocale}. There are ${locales.length} locales in total.`
    )
  } catch (e) {
    handleContentfulError({
      e,
      reporter,
      contentfulClientOptions,
      pluginConfig,
    })
  }

  // Fetch entries and assets via Contentful CDA sync API
  const pageLimit = pluginConfig.get(`pageLimit`)
  reporter.verbose(`Contentful: Sync ${pageLimit} items per page.`)
  const syncProgress = reporter.createProgress(
    `Contentful: ${syncToken ? `Sync changed items` : `Sync all items`}`,
    pageLimit,
    0
  )
  syncProgress.start()
  const contentfulSyncClientOptions = createContentfulClientOptions({
    pluginConfig,
    reporter,
    syncProgress,
  })
  const syncClient = createClient(
    contentfulSyncClientOptions
  ).withoutLinkResolution

  let currentSyncData
  let currentPageLimit = pageLimit
  let lastCurrentPageLimit
  let syncSuccess = false
  try {
    while (!syncSuccess) {
      try {
        const query = syncToken
          ? { nextSyncToken: syncToken }
          : { initial: true, limit: currentPageLimit }
        currentSyncData = await syncClient.sync(query)
        syncSuccess = true
      } catch (e) {
        // Back off page limit if responses content length exceeds Contentfuls limits.
        if (
          e.response?.data?.message.includes(`Response size too big`) &&
          currentPageLimit > 1
        ) {
          lastCurrentPageLimit = currentPageLimit
          // Reduce page limit by a arbitrary 1/3 of the current limit to ensure
          // the new and bigger entries are synced without exceeding the reponse size limit
          currentPageLimit = Math.floor((currentPageLimit / 3) * 2) || 1
          reporter.warn(
            [
              `The sync with Contentful failed using pageLimit ${lastCurrentPageLimit} as the reponse size limit of the API is exceeded.`,
              `Retrying sync with pageLimit of ${currentPageLimit}`,
            ].join(`\n\n`)
          )
          continue
        }
        throw e
      }
      if (currentPageLimit !== pageLimit) {
        reporter.warn(
          `We recommend you to set your pageLimit in gatsby-config.js to ${currentPageLimit} to avoid failed synchronizations.`
        )
      }
    }
  } catch (e) {
    reporter.panic({
      id: CODES.SyncError,
      context: {
        sourceMessage: `Fetching contentful data failed: ${createContentfulErrorMessage(
          e
        )}`,
      },
    })
  } finally {
    // Fix output when there was no new data in Contentful
    if (
      !currentSyncData?.entries.length &&
      !currentSyncData?.assets.length &&
      !currentSyncData?.deletedEntries.length &&
      !currentSyncData?.deletedAssets.length
    ) {
      syncProgress.tick()
      syncProgress.total = 1
    }

    syncProgress.done()
  }

  // We need to fetch tags with the non-sync API as the sync API doesn't support this.
  let tagItems = []
  if (pluginConfig.get(`enableTags`)) {
    try {
      const tagsResult = await pagedGet(client, `getTags`, pageLimit)
      tagItems = tagsResult.items
      reporter.verbose(`Tags fetched ${tagItems.length}`)
    } catch (e) {
      reporter.panic({
        id: CODES.FetchTags,
        context: {
          sourceMessage: `Error fetching tags: ${createContentfulErrorMessage(
            e
          )}`,
        },
      })
    }
  }

  const result = {
    currentSyncData,
    tagItems,
    defaultLocale,
    locales,
    space,
  }

  return result
}
Fetches:
* Locales with default locale
* Entries and assets
* Tags