All files / src/lib/helpers fsCopy.ts

90.7% Statements 39/43
82.61% Branches 19/23
83.33% Functions 5/6
90.7% Lines 39/43

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86  6x 6x                 6x         176x 176x 5x   171x 171x 2x 2x 2x 2x             2x 2x     169x 169x 169x 169x       169x 169x   169x       6x         45x 45x     45x 45x 45x 203x 203x 34x   169x         6x   18x 18x   18x 18x 11x   7x       6x  
/* eslint-disable no-await-in-loop */
import fs from "fs-extra";
import Path from "path";
 
interface CopyOptions {
  overwrite?: boolean;
  errorOnExist?: boolean;
  mode?: number | undefined;
  ignore?: (path: string) => boolean;
}
 
const copyFile = async (
  src: string,
  dest: string,
  options: CopyOptions = {},
) => {
  const { overwrite = true, errorOnExist = false, mode, ignore } = options;
  if (ignore?.(src)) {
    return;
  }
  let throwAlreadyExists = false;
  if (!overwrite) {
    try {
      await fs.lstat(dest);
      if (errorOnExist) {
        throwAlreadyExists = true;
      } else E{
        return;
      }
    } catch (e) {
      // Didn't exist so copy it
    }
    if (throwAlreadyExists) {
      throw new Error(`File already exists ${dest}`);
    }
  }
  await new Promise<void>((resolve, reject) => {
    const inputStream = fs.createReadStream(src);
    const outputStream = fs.createWriteStream(dest, { mode });
    inputStream.once("error", (err) => {
      outputStream.close();
      reject(new Error(`Could not write file ${dest}: ${err}`));
    });
    inputStream.once("end", () => {
      resolve();
    });
    inputStream.pipe(outputStream);
  });
};
 
const copyDir = async (
  src: string,
  dest: string,
  options: CopyOptions = {},
) => {
  const { ignore } = options;
  Iif (ignore?.(src)) {
    return;
  }
  const filePaths = await fs.readdir(src);
  await fs.ensureDir(dest);
  for (const fileName of filePaths) {
    const fileStat = await fs.lstat(`${src}/${fileName}`);
    if (fileStat.isDirectory()) {
      await copyDir(`${src}/${fileName}`, `${dest}/${fileName}`, options);
    } else {
      await copyFile(`${src}/${fileName}`, `${dest}/${fileName}`, options);
    }
  }
};
 
const copy = async (src: string, dest: string, options: CopyOptions = {}) => {
  // Ensure parent folder exists first
  const parentDir = Path.dirname(dest);
  await fs.ensureDir(parentDir);
 
  const fileStat = await fs.lstat(src);
  if (fileStat.isDirectory()) {
    await copyDir(src, dest, options);
  } else {
    await copyFile(src, dest, options);
  }
};
 
export default copy;