<commit_before>const _ = require('underscore')
const {Errors: {APIError}} = require('isomorphic-core')

const IMAPHelpers = {
  async messagesForThreadByFolder(db, threadId) {
    const thread = await db.Thread.findById(threadId)
    if (!thread) {
      throw new APIError(`IMAPHelpers.messagesForThreadByFolder - Can't find thread`, 404)
    }
    const messages = await thread.getMessages()
    return _.groupBy(messages, 'folderId')
  },

  async forEachFolderOfThread({db, imap, threadMessages, callback}) {
    const {Folder} = db
    const msgsByFolder = _.groupBy(threadMessages, 'folderId')
    const folderIds = Object.keys(msgsByFolder)
    const folders = await Folder.findAll({where: {id: folderIds}})

    for (const folder of folders) {
      const msgsInFolder = msgsByFolder[folder.id]
      if (msgsInFolder.length === 0) { continue }
      const messageImapUIDs = msgsInFolder.map(m => m.folderImapUID)
      const box = await imap.openBox(folder.name, {readOnly: false})
      await callback({folder, messages: msgsInFolder, messageImapUIDs, box})
    }
  },

  async forEachLabelSetOfMessages({messages, callback}) {<commit_msg>[local-sync] Ensure syncback actions have uids available before running<commit_after>const _ = require('underscore')
const {Errors: {APIError}} = require('isomorphic-core')

const IMAPHelpers = {
  async messagesForThreadByFolder(db, threadId) {
    const thread = await db.Thread.findById(threadId)
    if (!thread) {
      throw new APIError(`IMAPHelpers.messagesForThreadByFolder - Can't find thread`, 404)
    }
    const messages = await thread.getMessages()
    return _.groupBy(messages, 'folderId')
  },

  async forEachFolderOfThread({db, imap, threadMessages, callback}) {
    if (!threadMessages.every(m => m.folderImapUID != null)) {
      throw new APIError('All messages in a thread require an IMAP uid to perform an action')
    }
    const {Folder} = db
    const msgsByFolder = _.groupBy(threadMessages, 'folderId')
    const folderIds = Object.keys(msgsByFolder)
    const folders = await Folder.findAll({where: {id: folderIds}})

    for (const folder of folders) {
      const msgsInFolder = msgsByFolder[folder.id]
      if (msgsInFolder.length === 0) { continue }
      const messageImapUIDs = msgsInFolder.map(m => m.folderImapUID)
      const box = await imap.openBox(folder.name, {readOnly: false})
      await callback({folder, messages: msgsInFolder, messageImapUIDs, box})
    }
  },

  async forEachLabelSetOfMessages({messages, callback}) {
{'fraction_non_alphanumeric': 0.11512504962286621, 'fraction_numerical': 0.0031758634378721714, 'mean_word_length': 4.153374233128834, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '824897', 'n_tokens_mistral': 779, 'n_tokens_neox': 762, 'n_words': 193}