function createAssignAndStart({ available, claim, start, queue, recover, announce }) { let request = null; function run(item, { alreadyOwned = false, destination = 'start' } = {}) { if (request) return request; if (!available()) { announce('Today is full—remove an item before assigning this issue.'); return Promise.resolve('full'); } request = Promise.resolve() .then(() => alreadyOwned ? item : claim(item)) .then(confirmed => { const outcome = destination === 'queue' ? queue(confirmed) : start(confirmed); if (outcome === 'queued') { announce(alreadyOwned ? 'Queued in Today. Keep finding work when ready.' : 'Assigned and queued in Today. Keep finding work when ready.'); return outcome; } if (outcome === 'started') { announce(alreadyOwned ? 'Added to Today and ready to work.' : 'Assigned, added to Today, and ready to work.'); return outcome; } if (destination === 'queue') { if (outcome === 'sync-unavailable') { announce(alreadyOwned ? 'Saved in Today on this device, but account sync is unavailable. The issue is open so you can recover.' : 'Assigned and saved in Today on this device, but account sync is unavailable. The issue is open so you can recover.'); } else { announce(alreadyOwned ? 'Today could not be queued. The issue is open so you can recover.' : 'Assigned to you, but Today could not be queued. The issue is open so you can recover.'); } } else { announce(alreadyOwned ? 'Today could not start. The issue is open so you can recover.' : 'Assigned to you, but Today could not start. The issue is open so you can recover.'); } recover(confirmed); return 'recovery'; }) .finally(() => { request = null; }); return request; } return { run }; } if (typeof module !== 'undefined' && module.exports) module.exports = createAssignAndStart;