UNPKG

cogs

Version:

The fast file transform pipeline.

135 lines (118 loc) 3.65 kB
import fs from 'node:fs/promises'; import npath from 'node:path'; import _ from 'underscore'; import getBuild from './get-build.js'; import maybeWrite from './maybe-write.js'; import setExt from './set-ext.js'; import sortObj from './sort-obj.js'; import writeBuffer from './write-buffer.js'; const flattenBuilds = build => [build, ...build.builds.flatMap(flattenBuilds)]; const saveManifest = async ({ env, manifest, onError, onResult }) => { const { manifestPath } = env; if (!manifestPath) return; const buffer = Buffer.from(JSON.stringify(sortObj(manifest))); const size = buffer.length; const sourcePath = `[manifest:${env.name}]`; const targetPath = manifestPath; try { const didChange = await maybeWrite({ buffer, targetPath }); await onResult({ didChange, size, sourcePath, targetPath }); } catch (error) { await onError({ error, sourcePath }); } }; const saveBuild = async ({ build: { buffers, path }, manifest, onError, onResult, target }) => { manifest[path] = await Promise.all( buffers.map(async (buffer, i) => { const size = buffer.length; const sourcePath = i === 0 ? path : setExt(path, `~${i + 1}${npath.extname(path)}`); try { const { didChange, targetPath } = await writeBuffer({ buffer, path: sourcePath, target }); await onResult({ didChange, size, sourcePath, targetPath }); return targetPath; } catch (error) { await onError({ error, sourcePath }); } }) ); }; const getPaths = async pattern => { const paths = []; for await (const dirent of fs.glob(pattern, { withFileTypes: true })) { if (!dirent.isDirectory()) { paths.push( npath.relative('.', npath.join(dirent.parentPath, dirent.name)) ); } } return paths.sort(); }; const saveBuilds = async ({ env, manifest, onError, onResult }) => await Promise.all( _.map( env.builds, async (target, pattern) => await Promise.all( (await getPaths(pattern)).map(async path => { try { const builds = flattenBuilds( await getBuild({ env, maxChunkSize: target.maxChunkSize, path, transformers: target.transformers }) ); await Promise.all( _.map(builds, async build => { await saveBuild({ build, manifest, onError, onResult, target }); }) ); } catch (error) { await onError({ error, sourcePath: path }); } }) ) ) ); const buildConfig = async ({ built, config, onResult, started }) => { let failed = false; const onError = async ({ error, sourcePath }) => { failed = true; await onResult({ error, sourcePath }); }; await Promise.all( _.map(config, async env => { if (started.has(env) || !_.all(env.requires, env => built.has(env))) { return; } started.add(env); const manifest = {}; await saveBuilds({ env, manifest, onError, onResult }); if (failed) return; await saveManifest({ env, manifest, onError, onResult }); if (failed) return; built.add(env); await buildConfig({ built, config, onResult, started }); }) ); }; export default ({ config, onResult = _.noop }) => buildConfig({ built: new Set(), config, onResult, started: new Set() });