packages/metalsmith-build-cache/index.ts
import crypto from 'crypto';import fs from 'fs';import Metalsmith from 'metalsmith';import path from 'path'; export interface Options { cachePath?: string;} export default {Function `metalsmith` has 49 lines of code (exceeds 25 allowed). Consider refactoring.
Function `metalsmith` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring. metalsmith(realMetalsmith: Metalsmith, options: Options = {}): Metalsmith { const { run } = realMetalsmith; // @ts-expect-error Metalsmith.run()'s three different signatures makes TypeScript mad hereFunction `run` has 41 lines of code (exceeds 25 allowed). Consider refactoring. realMetalsmith.run = async ( inputFiles: Metalsmith.Files, argTwo: Metalsmith.Callback | Metalsmith.Plugin[] | undefined, argThree: Metalsmith.Callback | undefined, ) => { const plugins = Array.isArray(argTwo) ? argTwo : []; const callback = typeof argTwo === 'function' ? argTwo : argThree; // Hash the input file paths and their contents const hash = crypto.createHash('md5'); hash.update(plugins.length.toString()); Object.keys(inputFiles) .sort() .forEach((fileName) => { hash.update(fileName).update(inputFiles[fileName].contents); }); const filesHash = hash.digest('hex'); // Build a "marker" filename using the hash above const cachePath = path.join( realMetalsmith.directory(), options.cachePath ?? path.join( '.cache', path.relative(realMetalsmith.directory(), realMetalsmith.destination()), ), ); const cacheMarkerFile = path.join(cachePath, '.metalsmith-build-cache-' + filesHash); try { // Check for the existence of the marker file await fs.promises.lstat(cacheMarkerFile); // The marker file exists, therefore the cache is valid, so return the cache return Metalsmith(cachePath) .source('') .ignore(path.basename(cacheMarkerFile)) .destination(realMetalsmith.destination()) .clean(realMetalsmith.clean()) .build(); } catch { /* ignored */ } // The marker file does not exist, therefore the cache is either invalid or doesn't exist, // so run the build like normal // Process all input files const outputFiles = await run.apply(realMetalsmith, [inputFiles]); // Write the cache directory and the marker file await fs.promises.rm(cachePath, { recursive: true, force: true }); await Metalsmith(realMetalsmith.directory()) .destination(cachePath) .clean(true) .write(outputFiles); await fs.promises.writeFile(cacheMarkerFile, ''); // If a callback was passed then `Metalsmith.run()` won't return anything if (callback) { callback(null, outputFiles); return; } return outputFiles; }; return realMetalsmith; }, // TODO(cemmer): plugin(plugin: Metalsmith.Plugin): Metalsmith {}};