file-system.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import fs from "node:fs/promises"
  2. import path from "path"
  3. import os from "os"
  4. import { glob } from "glob"
  5. export async function fileExists(filePath) {
  6. try {
  7. await fs.stat(filePath)
  8. return true
  9. } catch (err) {
  10. if (err.code === "ENOENT") {
  11. return false
  12. }
  13. throw err // re-throw other errors
  14. }
  15. }
  16. export async function readDirectoryRecursively(dir, files = []) {
  17. const exists = await fileExists(dir)
  18. if (!exists) {
  19. return files
  20. }
  21. const contents = await fs.readdir(dir, { withFileTypes: true })
  22. for (const item of contents) {
  23. const itemPath = path.join(dir, item.name)
  24. if (item.isDirectory()) {
  25. readDirectoryRecursively(itemPath, files)
  26. } else {
  27. files.push(itemPath)
  28. }
  29. }
  30. return files
  31. }
  32. // type InputConfig
  33. // {
  34. // pattern: String | String[];
  35. // ignore: String | String[];
  36. // }
  37. export async function readFilesByGlob(globConfigs) {
  38. const matchPromises = globConfigs.reduce(
  39. async (existingMatches, globConfig) => {
  40. const { pattern, ignore, dot } = {
  41. dot: false,
  42. ignore: [],
  43. ...globConfig,
  44. }
  45. const matches = await glob(expandTilde(pattern), {
  46. ignore,
  47. dot,
  48. })
  49. return [...(await existingMatches), ...matches]
  50. },
  51. [],
  52. )
  53. const files = await matchPromises
  54. return [...new Set(files)]
  55. }
  56. export function expandTilde(path) {
  57. if (!path.startsWith("~")) return path
  58. return path.replace(/^~(?=$|\/|\\)/, os.homedir())
  59. }
  60. export async function checkFilesExist(files, baseDir) {
  61. const filesToCheck = Array.isArray(files) ? files : [files]
  62. const fileCheckResults = await Promise.all(
  63. filesToCheck.map(async file => {
  64. const filePath = path.join(baseDir, file)
  65. const exists = await fileExists(filePath)
  66. return { filePath, exists }
  67. }),
  68. )
  69. return fileCheckResults.reduce(
  70. (sorted, { filePath, exists }) => {
  71. return exists
  72. ? { ...sorted, present: [...sorted.present, filePath] }
  73. : { ...sorted, absent: [...sorted.absent, filePath] }
  74. },
  75. { present: [], absent: [] },
  76. )
  77. }
  78. export async function writeFile(filePath, content) {
  79. const fileDir = path.dirname(filePath)
  80. await fs.mkdir(fileDir, { recursive: true })
  81. return await fs.writeFile(filePath, content, {
  82. encoding: "utf8",
  83. })
  84. }