util.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import child_process, { type ExecOptions } from 'node:child_process'
  2. import crypto from 'node:crypto'
  3. import fs from 'node:fs'
  4. import os from 'node:os'
  5. import path from 'node:path'
  6. import util from 'node:util'
  7. import { PLUGIN_NAME } from './constant'
  8. /**
  9. * Check if file exists
  10. *
  11. * @param filePath file path
  12. * @returns does the file exist
  13. */
  14. export const exists = async (filePath: string) => {
  15. try {
  16. await fs.promises.access(filePath)
  17. return true
  18. } catch (_error) {
  19. return false
  20. }
  21. }
  22. export const mkdir = async (dirname: string) => {
  23. const isExist = await exists(dirname)
  24. if (!isExist) {
  25. await fs.promises.mkdir(dirname, { recursive: true })
  26. }
  27. }
  28. export const ensureDirExist = async (filePath: string, strip = false) => {
  29. const dirname = strip ? path.dirname(filePath) : filePath
  30. await mkdir(dirname)
  31. }
  32. export const readFile = async (filePath: string) => {
  33. const isExist = await exists(filePath)
  34. return isExist ? (await fs.promises.readFile(filePath)).toString() : undefined
  35. }
  36. export const writeFile = async (
  37. filePath: string,
  38. data: string | Uint8Array
  39. ) => {
  40. await ensureDirExist(filePath, true)
  41. await fs.promises.writeFile(filePath, data)
  42. await fs.promises.chmod(filePath, 0o777)
  43. }
  44. export const readDir = async (source: string) => {
  45. return fs.promises.readdir(source)
  46. }
  47. export const copyDir = async (source: string, dest: string) => {
  48. try {
  49. await fs.promises.cp(source, dest, {
  50. recursive: true
  51. })
  52. } catch (error: any) {
  53. // Fails when nodejs version < 16.7.0, ignore?
  54. console.log(`${PLUGIN_NAME}:`, error)
  55. }
  56. }
  57. export const exec = async (cmd: string, options?: ExecOptions) => {
  58. return util.promisify(child_process.exec)(cmd, options)
  59. }
  60. /**
  61. * http://nodejs.cn/api/os/os_networkinterfaces.html
  62. */
  63. const isIPV4 = (family: string | number) => {
  64. return family === 'IPv4' || family === 4
  65. }
  66. export const getLocalV4Ips = () => {
  67. const interfaceDict = os.networkInterfaces()
  68. const addresses: string[] = []
  69. for (const key in interfaceDict) {
  70. const interfaces = interfaceDict[key]
  71. if (interfaces) {
  72. for (const item of interfaces) {
  73. if (isIPV4(item.family)) {
  74. addresses.push(item.address)
  75. }
  76. }
  77. }
  78. }
  79. return addresses
  80. }
  81. export const getDefaultHosts = () => {
  82. return ['localhost', ...getLocalV4Ips()]
  83. }
  84. export const getHash = async (filePath: string) => {
  85. const content = await readFile(filePath)
  86. if (content) {
  87. const hash = crypto.createHash('sha256')
  88. hash.update(content)
  89. return hash.digest('hex')
  90. }
  91. return undefined
  92. }
  93. const isObj = (obj: any) =>
  94. Object.prototype.toString.call(obj) === '[object Object]'
  95. const mergeObj = (target: any, source: any) => {
  96. if (!(isObj(target) && isObj(source))) {
  97. return target
  98. }
  99. for (const key in source) {
  100. if (Object.prototype.hasOwnProperty.call(source, key)) {
  101. const targetValue = target[key]
  102. const sourceValue = source[key]
  103. if (isObj(targetValue) && isObj(sourceValue)) {
  104. mergeObj(targetValue, sourceValue)
  105. } else {
  106. target[key] = sourceValue
  107. }
  108. }
  109. }
  110. }
  111. export const deepMerge = (target: any, ...source: any[]) => {
  112. return source.reduce((a, b) => mergeObj(a, b), target)
  113. }
  114. export const prettyLog = (obj?: Record<string, any>) => {
  115. return JSON.stringify(obj, null, 2)
  116. }
  117. export const escapeStr = (path?: string) => {
  118. return `"${path}"`
  119. }