@netlify/cache-utils
Version:
Utility for caching files in Netlify Build
72 lines (71 loc) • 2.42 kB
JavaScript
import { promises as fs } from 'fs';
import { basename, dirname, join } from 'path';
import cpy from 'cpy';
import { globby } from 'globby';
import { isNotJunk } from 'junk';
import { moveFile } from 'move-file';
/**
* Move or copy a cached file/directory from/to a local one
* @param src The src directory or file to cache
* @param dest The destination location
* @param move If the file should be moved, moving is faster but removes the source files locally
*/
export const moveCacheFile = async function (src, dest, move = false) {
// Moving is faster but removes the source files locally
if (move) {
return moveFile(src, dest, { overwrite: false });
}
const { srcGlob, dest: matchedDest, ...options } = await getSrcAndDest(src, dirname(dest));
if (srcGlob && matchedDest) {
return cpy(srcGlob, matchedDest, { ...options, overwrite: false });
}
};
/**
* Non-existing files and empty directories are always skipped
*/
export const hasFiles = async function (src) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { srcGlob, isDir, dest, ...options } = await getSrcAndDest(src, '');
return srcGlob !== undefined && !(await isEmptyDir(srcGlob, isDir, options));
};
/** Replicates what `cpy` is doing under the hood. */
const isEmptyDir = async function (globPattern, isDir, options) {
if (!isDir) {
return false;
}
const files = await globby(globPattern, options);
const filteredFiles = files.filter((file) => isNotJunk(basename(file)));
return filteredFiles.length === 0;
};
/**
* Get globbing pattern with files to move/copy
*/
const getSrcAndDest = async function (src, dest) {
const srcStat = await getStat(src);
if (srcStat === undefined) {
return { srcGlob: undefined, isDir: false, cwd: '' };
}
const isDir = srcStat.isDirectory();
const srcBasename = basename(src);
const cwd = dirname(src);
const baseOptions = {
srcGlob: srcBasename,
dest,
isDir,
cwd,
dot: true, // collect .dot directories as well
};
if (isDir) {
return { ...baseOptions, srcGlob: `${srcBasename}/**`, dest: join(dest, srcBasename) };
}
return baseOptions;
};
const getStat = async (src) => {
try {
return await fs.stat(src);
}
catch {
// continue regardless error
return undefined;
}
};