UNPKG

@jakehamilton/titan

Version:

A little tool for big (monorepo) projects.

157 lines (123 loc) 4.33 kB
const AbortController = require("abort-controller"); const cache = require("./cache"); const log = require("./log"); const colors = require("./colors"); const { pkgsToDependencyMap } = require("./npm"); const runTasks = async (map, options, signal, cb, onError) => { if (signal.aborted) { return; } let itemsToBuild = []; for (const item of map.values()) { if (item.dependencies.size === 0) { itemsToBuild.push(item); } } return await Promise.all( itemsToBuild.map(async (item) => { map.delete(item.pkg.config.name); const color = colors.unique(); if (options.cache) { const cacheStatus = await cache.getCacheStatus(item.pkg); item.useCache = item.useCache || cacheStatus.useCache; } if (item.useCache) { log.info(color(`${item.pkg.config.name} using cache.`)); } try { const promise = item.useCache ? Promise.resolve() : cb(item.pkg, options, color, signal); await promise; for (const otherItem of map.values()) { if (otherItem.dependencies.has(item.pkg.config.name)) { otherItem.dependencies.delete(item.pkg.config.name); if (item.useCache) { otherItem.useCache = true; } } } if (options.cache) { const newCacheStatus = await cache.getCacheStatus(item.pkg); cache.updateCacheMap(newCacheStatus); } return await runTasks(map, options, signal, cb, onError); } catch (error) { log.fatal(error); onError(error); } }) ); }; const executeOrdered = async (map, options, cb) => { if (cb === undefined && typeof options === "function") { cb = options; options = {}; } else if (typeof cb === undefined) { throw new Error(`No callback provided to "task.executeUnordered".`); } const controller = new AbortController(); try { await runTasks(map, options, controller.signal, cb, () => { controller.abort(); }); } catch (error) { controller.abort(); } }; const executeUnordered = async (pkgs, options, cb) => { if (cb === undefined && typeof options === "function") { cb = options; options = {}; } else if (typeof cb === undefined) { throw new Error(`No callback provided to "task.executeUnordered".`); } const controller = new AbortController(); try { await Promise.all( pkgs.map(async (pkg) => { let useCache = false; if (options.cache) { const cacheStatus = await cache.getCacheStatus(pkg); useCache = cacheStatus.useCache; } const color = colors.unique(); if (useCache) { log.info(color(`${pkg.config.name} using cache.`)); } const promise = useCache ? Promise.resolve() : cb(pkg, options, color, controller.signal); await promise; if (options.cache) { const newCacheStatus = await cache.getCacheStatus(item.pkg); cache.updateCacheMap(newCacheStatus); } }) ); } catch (error) { controller.abort(); } }; const execute = async (pkgs, options, cb) => { if (cb === undefined && typeof options === "function") { cb = options; options = {}; } else if (typeof cb === undefined) { throw new Error(`No callback provided to "task.execute".`); } const { ordered = false } = options; if (ordered) { await executeOrdered(pkgsToDependencyMap(pkgs), options, cb); } else { await executeUnordered(pkgs, options, cb); } if (options.cache) { cache.writeCacheMap(); } }; module.exports = { execute, executeOrdered, executeUnordered, };