util.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import child_process, { ExecOptions } from 'child_process'
  2. import crypto from 'crypto'
  3. import fs from 'fs'
  4. import os from 'os'
  5. import path from 'path'
  6. import util from 'util'
  7. import { PLUGIN_DATA_DIR } 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. /**
  23. * Resolve file path with `PLUGIN_DATA_DIR`
  24. *
  25. * @param fileName file name
  26. * @returns absolute path
  27. */
  28. export const resolvePath = (fileName: string) => {
  29. return path.resolve(PLUGIN_DATA_DIR, fileName)
  30. }
  31. export const mkdir = async (dirname: string) => {
  32. const isExist = await exists(dirname)
  33. if (!isExist) {
  34. await fs.promises.mkdir(dirname, { recursive: true })
  35. }
  36. }
  37. export const ensureDirExist = async (filePath: string) => {
  38. const dirname = path.dirname(filePath)
  39. await mkdir(dirname)
  40. }
  41. export const readFile = async (filePath: string) => {
  42. const isExist = await exists(filePath)
  43. return isExist ? (await fs.promises.readFile(filePath)).toString() : undefined
  44. }
  45. export const writeFile = async (
  46. filePath: string,
  47. data: string | Uint8Array
  48. ) => {
  49. await ensureDirExist(filePath)
  50. await fs.promises.writeFile(filePath, data)
  51. await fs.promises.chmod(filePath, 0o777)
  52. }
  53. export const exec = async (cmd: string, options?: ExecOptions) => {
  54. return await util.promisify(child_process.exec)(cmd, options)
  55. }
  56. /**
  57. * http://nodejs.cn/api/os/os_networkinterfaces.html
  58. */
  59. const isIPV4 = (family: string | number) => {
  60. return family === 'IPv4' || family === 4
  61. }
  62. export const getLocalV4Ips = () => {
  63. const interfaceDict = os.networkInterfaces()
  64. const addresses: string[] = []
  65. for (const key in interfaceDict) {
  66. const interfaces = interfaceDict[key]
  67. if (interfaces) {
  68. for (const item of interfaces) {
  69. if (isIPV4(item.family)) {
  70. addresses.push(item.address)
  71. }
  72. }
  73. }
  74. }
  75. return addresses
  76. }
  77. export const getDefaultHosts = () => {
  78. return ['localhost', ...getLocalV4Ips()]
  79. }
  80. export const getHash = async (filePath: string) => {
  81. const content = await readFile(filePath)
  82. if (content) {
  83. const hash = crypto.createHash('sha256')
  84. hash.update(content)
  85. return hash.digest('hex')
  86. }
  87. return undefined
  88. }
  89. const isObj = (obj: any) =>
  90. Object.prototype.toString.call(obj) === '[object Object]'
  91. const mergeObj = (target: any, source: any) => {
  92. if (!(isObj(target) && isObj(source))) {
  93. return target
  94. }
  95. for (const key in source) {
  96. if (Object.prototype.hasOwnProperty.call(source, key)) {
  97. const targetValue = target[key]
  98. const sourceValue = source[key]
  99. if (isObj(targetValue) && isObj(sourceValue)) {
  100. mergeObj(targetValue, sourceValue)
  101. } else {
  102. target[key] = sourceValue
  103. }
  104. }
  105. }
  106. }
  107. export const deepMerge = (target: any, ...source: any[]) => {
  108. return source.reduce((a, b) => mergeObj(a, b), target)
  109. }
  110. export const prettyLog = (obj?: Record<string, any>) => {
  111. return JSON.stringify(obj, null, 2)
  112. }
  113. export const escape = (path?: string) => {
  114. return `"${path}"`
  115. }