index.js 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. const { dirname } = require('path')
  2. const { promisify } = require('util')
  3. const {
  4. access: access_,
  5. accessSync,
  6. copyFile: copyFile_,
  7. copyFileSync,
  8. unlink: unlink_,
  9. unlinkSync,
  10. rename: rename_,
  11. renameSync,
  12. } = require('fs')
  13. const access = promisify(access_)
  14. const copyFile = promisify(copyFile_)
  15. const unlink = promisify(unlink_)
  16. const rename = promisify(rename_)
  17. const mkdirp = require('mkdirp')
  18. const pathExists = async path => {
  19. try {
  20. await access(path)
  21. return true
  22. } catch (er) {
  23. return er.code !== 'ENOENT'
  24. }
  25. }
  26. const pathExistsSync = path => {
  27. try {
  28. accessSync(path)
  29. return true
  30. } catch (er) {
  31. return er.code !== 'ENOENT'
  32. }
  33. }
  34. module.exports = async (source, destination, options = {}) => {
  35. if (!source || !destination) {
  36. throw new TypeError('`source` and `destination` file required')
  37. }
  38. options = {
  39. overwrite: true,
  40. ...options
  41. }
  42. if (!options.overwrite && await pathExists(destination)) {
  43. throw new Error(`The destination file exists: ${destination}`)
  44. }
  45. await mkdirp(dirname(destination))
  46. try {
  47. await rename(source, destination)
  48. } catch (error) {
  49. if (error.code === 'EXDEV') {
  50. await copyFile(source, destination)
  51. await unlink(source)
  52. } else {
  53. throw error
  54. }
  55. }
  56. }
  57. module.exports.sync = (source, destination, options = {}) => {
  58. if (!source || !destination) {
  59. throw new TypeError('`source` and `destination` file required')
  60. }
  61. options = {
  62. overwrite: true,
  63. ...options
  64. }
  65. if (!options.overwrite && pathExistsSync(destination)) {
  66. throw new Error(`The destination file exists: ${destination}`)
  67. }
  68. mkdirp.sync(dirname(destination))
  69. try {
  70. renameSync(source, destination)
  71. } catch (error) {
  72. if (error.code === 'EXDEV') {
  73. copyFileSync(source, destination)
  74. unlinkSync(source)
  75. } else {
  76. throw error
  77. }
  78. }
  79. }