All files / src/lib/helpers fsCopy.ts

88.37% Statements 38/43
69.57% Branches 16/23
83.33% Functions 5/6
88.37% Lines 38/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  5x 5x                 5x         147x 147x     147x 147x 2x 2x 2x 2x             2x 2x     145x 145x 145x 145x       145x 145x   145x       5x         35x 35x     35x 35x 35x 179x 179x 34x   145x         5x   3x 3x   3x 3x 1x   2x       5x  
/* 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;
  Iif (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;