tree-dir.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import fsp from 'node:fs/promises';
  2. import { sep } from 'node:path';
  3. interface TreeFileType {
  4. type: 'file',
  5. name: string,
  6. path: string
  7. }
  8. interface TreeDirectoryType {
  9. type: 'directory',
  10. name: string,
  11. path: string,
  12. children: TreeTypeArray
  13. }
  14. export type TreeType = TreeDirectoryType | TreeFileType;
  15. export type TreeTypeArray = TreeType[];
  16. type VoidOrVoidArray = void | VoidOrVoidArray[];
  17. export async function treeDir(rootPath: string): Promise<TreeTypeArray> {
  18. const tree: TreeTypeArray = [];
  19. const walk = async (dir: string, node: TreeTypeArray, dirRelativeToRoot = ''): Promise<VoidOrVoidArray> => {
  20. const promises: Array<Promise<VoidOrVoidArray>> = [];
  21. for await (const child of await fsp.opendir(dir)) {
  22. // Ignore hidden files
  23. if (child.name[0] === '.' || child.name === 'CNAME') {
  24. continue;
  25. }
  26. const childFullPath = child.parentPath + sep + child.name;
  27. const childRelativeToRoot = dirRelativeToRoot + sep + child.name;
  28. if (child.isDirectory()) {
  29. const newNode: TreeDirectoryType = {
  30. type: 'directory',
  31. name: child.name,
  32. path: childRelativeToRoot,
  33. children: []
  34. };
  35. node.push(newNode);
  36. promises.push(walk(childFullPath, newNode.children, childRelativeToRoot));
  37. continue;
  38. }
  39. if (child.isFile()) {
  40. const newNode: TreeFileType = {
  41. type: 'file',
  42. name: child.name,
  43. path: childRelativeToRoot
  44. };
  45. node.push(newNode);
  46. continue;
  47. }
  48. }
  49. return Promise.all(promises);
  50. };
  51. await walk(rootPath, tree);
  52. return tree;
  53. }