| const { dirname, join, resolve, relative, isAbsolute } = require('path') | 
| const rimraf_ = require('rimraf') | 
| const { promisify } = require('util') | 
| const { | 
|   access: access_, | 
|   accessSync, | 
|   copyFile: copyFile_, | 
|   copyFileSync, | 
|   unlink: unlink_, | 
|   unlinkSync, | 
|   readdir: readdir_, | 
|   readdirSync, | 
|   rename: rename_, | 
|   renameSync, | 
|   stat: stat_, | 
|   statSync, | 
|   lstat: lstat_, | 
|   lstatSync, | 
|   symlink: symlink_, | 
|   symlinkSync, | 
|   readlink: readlink_, | 
|   readlinkSync | 
| } = require('fs') | 
|   | 
| const access = promisify(access_) | 
| const copyFile = promisify(copyFile_) | 
| const unlink = promisify(unlink_) | 
| const readdir = promisify(readdir_) | 
| const rename = promisify(rename_) | 
| const stat = promisify(stat_) | 
| const lstat = promisify(lstat_) | 
| const symlink = promisify(symlink_) | 
| const readlink = promisify(readlink_) | 
| const rimraf = promisify(rimraf_) | 
| const rimrafSync = rimraf_.sync | 
|   | 
| const mkdirp = require('mkdirp') | 
|   | 
| const pathExists = async path => { | 
|   try { | 
|     await access(path) | 
|     return true | 
|   } catch (er) { | 
|     return er.code !== 'ENOENT' | 
|   } | 
| } | 
|   | 
| const pathExistsSync = path => { | 
|   try { | 
|     accessSync(path) | 
|     return true | 
|   } catch (er) { | 
|     return er.code !== 'ENOENT' | 
|   } | 
| } | 
|   | 
| const moveFile = async (source, destination, options = {}, root = true, symlinks = []) => { | 
|   if (!source || !destination) { | 
|     throw new TypeError('`source` and `destination` file required') | 
|   } | 
|   | 
|   options = { | 
|     overwrite: true, | 
|     ...options | 
|   } | 
|   | 
|   if (!options.overwrite && await pathExists(destination)) { | 
|     throw new Error(`The destination file exists: ${destination}`) | 
|   } | 
|   | 
|   await mkdirp(dirname(destination)) | 
|   | 
|   try { | 
|     await rename(source, destination) | 
|   } catch (error) { | 
|     if (error.code === 'EXDEV' || error.code === 'EPERM') { | 
|       const sourceStat = await lstat(source) | 
|       if (sourceStat.isDirectory()) { | 
|         const files = await readdir(source) | 
|         await Promise.all(files.map((file) => moveFile(join(source, file), join(destination, file), options, false, symlinks))) | 
|       } else if (sourceStat.isSymbolicLink()) { | 
|         symlinks.push({ source, destination }) | 
|       } else { | 
|         await copyFile(source, destination) | 
|       } | 
|     } else { | 
|       throw error | 
|     } | 
|   } | 
|   | 
|   if (root) { | 
|     await Promise.all(symlinks.map(async ({ source, destination }) => { | 
|       let target = await readlink(source) | 
|       // junction symlinks in windows will be absolute paths, so we need to make sure they point to the destination | 
|       if (isAbsolute(target)) | 
|         target = resolve(destination, relative(source, target)) | 
|       // try to determine what the actual file is so we can create the correct type of symlink in windows | 
|       let targetStat | 
|       try { | 
|         targetStat = await stat(resolve(dirname(source), target)) | 
|       } catch (err) {} | 
|       await symlink(target, destination, targetStat && targetStat.isDirectory() ? 'junction' : 'file') | 
|     })) | 
|     await rimraf(source) | 
|   } | 
| } | 
|   | 
| const moveFileSync = (source, destination, options = {}, root = true, symlinks = []) => { | 
|   if (!source || !destination) { | 
|     throw new TypeError('`source` and `destination` file required') | 
|   } | 
|   | 
|   options = { | 
|     overwrite: true, | 
|     ...options | 
|   } | 
|   | 
|   if (!options.overwrite && pathExistsSync(destination)) { | 
|     throw new Error(`The destination file exists: ${destination}`) | 
|   } | 
|   | 
|   mkdirp.sync(dirname(destination)) | 
|   | 
|   try { | 
|     renameSync(source, destination) | 
|   } catch (error) { | 
|     if (error.code === 'EXDEV' || error.code === 'EPERM') { | 
|       const sourceStat = lstatSync(source) | 
|       if (sourceStat.isDirectory()) { | 
|         const files = readdirSync(source) | 
|         for (const file of files) { | 
|           moveFileSync(join(source, file), join(destination, file), options, false, symlinks) | 
|         } | 
|       } else if (sourceStat.isSymbolicLink()) { | 
|         symlinks.push({ source, destination }) | 
|       } else { | 
|         copyFileSync(source, destination) | 
|       } | 
|     } else { | 
|       throw error | 
|     } | 
|   } | 
|   | 
|   if (root) { | 
|     for (const { source, destination } of symlinks) { | 
|       let target = readlinkSync(source) | 
|       // junction symlinks in windows will be absolute paths, so we need to make sure they point to the destination | 
|       if (isAbsolute(target)) | 
|         target = resolve(destination, relative(source, target)) | 
|       // try to determine what the actual file is so we can create the correct type of symlink in windows | 
|       let targetStat | 
|       try { | 
|         targetStat = statSync(resolve(dirname(source), target)) | 
|       } catch (err) {} | 
|       symlinkSync(target, destination, targetStat && targetStat.isDirectory() ? 'junction' : 'file') | 
|     } | 
|     rimrafSync(source) | 
|   } | 
| } | 
|   | 
| module.exports = moveFile | 
| module.exports.sync = moveFileSync |