Mailspring/packages/nylas-sync/imap/fetch-folder-list.js
Juan Tejada 0c900b072d Add new relic to all pkgs + Revert to PromiseUtils methods
- PromiseUtils does not conflict with newrelics changes to Promise
- Other misc fixes
2016-07-13 19:08:24 -07:00

120 lines
3.3 KiB
JavaScript

const {Provider, PromiseUtils} = require('nylas-core');
const GMAIL_ROLES_WITH_FOLDERS = ['all', 'trash', 'junk'];
class FetchFolderList {
constructor(provider, logger) {
this._provider = provider;
this._logger = logger;
if (!this._logger) {
throw new Error("FetchFolderList requires a logger")
}
}
description() {
return `FetchFolderList`;
}
_classForMailboxWithRole(role, {Folder, Label}) {
if (this._provider === Provider.Gmail) {
return GMAIL_ROLES_WITH_FOLDERS.includes(role) ? Folder : Label;
}
return Folder;
}
_roleForMailbox(boxName, box) {
for (const attrib of (box.attribs || [])) {
const role = {
'\\Sent': 'sent',
'\\Drafts': 'drafts',
'\\Junk': 'junk',
'\\Trash': 'trash',
'\\All': 'all',
'\\Important': 'important',
'\\Flagged': 'flagged',
}[attrib];
if (role) {
return role;
}
}
if (boxName.toLowerCase().trim() === 'inbox') {
return 'inbox';
}
return null;
}
_updateCategoriesWithBoxes(categories, boxes) {
const stack = [];
const created = [];
const next = [];
Object.keys(boxes).forEach((boxName) => {
stack.push([boxName, boxes[boxName]]);
});
while (stack.length > 0) {
const [boxName, box] = stack.pop();
if (!box.attribs) {
// Some boxes seem to come back as partial objects. Not sure why, but
// I also can't access them via openMailbox. Possible node-imap i8n issue?
continue;
}
this._logger.info({
box_name: boxName,
attributes: JSON.stringify(box.attribs),
}, `FetchFolderList: Box Information`)
if (box.children && box.attribs.includes('\\HasChildren')) {
Object.keys(box.children).forEach((subname) => {
stack.push([`${boxName}${box.delimiter}${subname}`, box.children[subname]]);
});
}
let category = categories.find((cat) => cat.name === boxName);
if (!category) {
const role = this._roleForMailbox(boxName, box);
const Klass = this._classForMailboxWithRole(role, this._db);
category = Klass.build({
name: boxName,
accountId: this._db.accountId,
role: role,
});
created.push(category);
}
next.push(category);
}
// Todo: decide whether these are renames or deletes
const deleted = categories.filter(cat => !next.includes(cat));
return {next, created, deleted};
}
run(db, imap) {
this._db = db;
return imap.getBoxes().then((boxes) => {
const {Folder, Label, sequelize} = this._db;
return sequelize.transaction((transaction) => {
return PromiseUtils.props({
folders: Folder.findAll({transaction}),
labels: Label.findAll({transaction}),
}).then(({folders, labels}) => {
const all = [].concat(folders, labels);
const {created, deleted} = this._updateCategoriesWithBoxes(all, boxes);
let promises = [Promise.resolve()]
promises = promises.concat(created.map(cat => cat.save({transaction})))
promises = promises.concat(deleted.map(cat => cat.destroy({transaction})))
return Promise.all(promises)
});
});
});
}
}
module.exports = FetchFolderList;