utils.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. const fs = require('fs')
  2. const path = require('path')
  3. // eslint-disable-next-line no-unused-vars
  4. const colors = require('colors')
  5. const through = require('through2')
  6. /**
  7. * 异步函数封装
  8. */
  9. function wrap(func, scope) {
  10. return function (...args) {
  11. if (args.length) {
  12. const temp = args.pop()
  13. if (typeof temp !== 'function') {
  14. args.push(temp)
  15. }
  16. }
  17. return new Promise(function (resolve, reject) {
  18. args.push(function (err, data) {
  19. if (err) reject(err)
  20. else resolve(data)
  21. })
  22. func.apply((scope || null), args)
  23. })
  24. }
  25. }
  26. const accessSync = wrap(fs.access)
  27. const statSync = wrap(fs.stat)
  28. const renameSync = wrap(fs.rename)
  29. const mkdirSync = wrap(fs.mkdir)
  30. const readFileSync = wrap(fs.readFile)
  31. const writeFileSync = wrap(fs.writeFile)
  32. /**
  33. * 调整路径分隔符
  34. */
  35. function transformPath(filePath, sep = '/') {
  36. return filePath.replace(/[\\/]/g, sep)
  37. }
  38. /**
  39. * 检查文件是否存在
  40. */
  41. async function checkFileExists(filePath) {
  42. try {
  43. await accessSync(filePath)
  44. return true
  45. } catch (err) {
  46. return false
  47. }
  48. }
  49. /**
  50. * 递归创建目录
  51. */
  52. async function recursiveMkdir(dirPath) {
  53. const prevDirPath = path.dirname(dirPath)
  54. try {
  55. await accessSync(prevDirPath)
  56. } catch (err) {
  57. // 上一级目录不存在
  58. await recursiveMkdir(prevDirPath)
  59. }
  60. try {
  61. await accessSync(dirPath)
  62. const stat = await statSync(dirPath)
  63. if (stat && !stat.isDirectory()) {
  64. // 目标路径存在,但不是目录
  65. await renameSync(dirPath, `${dirPath}.bak`) // 将此文件重命名为 .bak 后缀
  66. await mkdirSync(dirPath)
  67. }
  68. } catch (err) {
  69. // 目标路径不存在
  70. await mkdirSync(dirPath)
  71. }
  72. }
  73. /**
  74. * 读取 json
  75. */
  76. function readJson(filePath) {
  77. try {
  78. // eslint-disable-next-line import/no-dynamic-require
  79. const content = require(filePath)
  80. delete require.cache[require.resolve(filePath)]
  81. return content
  82. } catch (err) {
  83. return null
  84. }
  85. }
  86. /**
  87. * 读取文件
  88. */
  89. async function readFile(filePath) {
  90. try {
  91. return await readFileSync(filePath, 'utf8')
  92. } catch (err) {
  93. // eslint-disable-next-line no-console
  94. return console.error(err)
  95. }
  96. }
  97. /**
  98. * 写文件
  99. */
  100. async function writeFile(filePath, data) {
  101. try {
  102. await recursiveMkdir(path.dirname(filePath))
  103. return await writeFileSync(filePath, data, 'utf8')
  104. } catch (err) {
  105. // eslint-disable-next-line no-console
  106. return console.error(err)
  107. }
  108. }
  109. /**
  110. * 时间格式化
  111. */
  112. function format(time, reg) {
  113. const date = typeof time === 'string' ? new Date(time) : time
  114. const map = {}
  115. map.yyyy = date.getFullYear()
  116. map.yy = ('' + map.yyyy).substr(2)
  117. map.M = date.getMonth() + 1
  118. map.MM = (map.M < 10 ? '0' : '') + map.M
  119. map.d = date.getDate()
  120. map.dd = (map.d < 10 ? '0' : '') + map.d
  121. map.H = date.getHours()
  122. map.HH = (map.H < 10 ? '0' : '') + map.H
  123. map.m = date.getMinutes()
  124. map.mm = (map.m < 10 ? '0' : '') + map.m
  125. map.s = date.getSeconds()
  126. map.ss = (map.s < 10 ? '0' : '') + map.s
  127. return reg.replace(/\byyyy|yy|MM|M|dd|d|HH|H|mm|m|ss|s\b/g, $1 => map[$1])
  128. }
  129. /**
  130. * 日志插件
  131. */
  132. function logger(action = 'copy') {
  133. return through.obj(function (file, enc, cb) {
  134. const type = path.extname(file.path).slice(1).toLowerCase()
  135. // eslint-disable-next-line no-console
  136. console.log(`[${format(new Date(), 'yyyy-MM-dd HH:mm:ss').grey}] [${action.green} ${type.green}] ${'=>'.cyan} ${file.path}`)
  137. this.push(file)
  138. cb()
  139. })
  140. }
  141. /**
  142. * 比较数组是否相等
  143. */
  144. function compareArray(arr1, arr2) {
  145. if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false
  146. if (arr1.length !== arr2.length) return false
  147. for (let i = 0, len = arr1.length; i < len; i++) {
  148. if (arr1[i] !== arr2[i]) return false
  149. }
  150. return true
  151. }
  152. /**
  153. * 合并两个对象
  154. */
  155. function merge(obj1, obj2) {
  156. Object.keys(obj2).forEach(key => {
  157. if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) {
  158. obj1[key] = obj1[key].concat(obj2[key])
  159. } else if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') {
  160. obj1[key] = Object.assign(obj1[key], obj2[key])
  161. } else {
  162. obj1[key] = obj2[key]
  163. }
  164. })
  165. return obj1
  166. }
  167. /**
  168. * 获取 id
  169. */
  170. let seed = +new Date()
  171. function getId() {
  172. return ++seed
  173. }
  174. module.exports = {
  175. wrap,
  176. transformPath,
  177. checkFileExists,
  178. readJson,
  179. readFile,
  180. writeFile,
  181. logger,
  182. format,
  183. compareArray,
  184. merge,
  185. getId,
  186. }