{"version":3,"file":"tree.js","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Provides {@link toTree a function} to dump the contents of a `Volume`,\n * comparing it to the real filesystem.\n *\n * Portions of this code adapted from\n * https://github.com/streamich/memfs/blob/2c6a6ca55ad2e661f40e488fe5ea4087438bae0e/src/print/index.ts#L6-L30\n * and are copyrighted by the original author and licesned under Apache-2.0.\n */\n\nimport type { Volume } from 'memfs';\nimport type { IDirent } from 'memfs/lib/node/types/misc.js';\n\nimport nodeFs, { type Dirent } from 'node:fs';\nimport path from 'node:path';\nimport { basename, sep } from 'path/posix';\nimport { printTree } from 'tree-dump';\n\nexport const toTree = (\n  fs: Volume,\n  {\n    depth = 10,\n    separator = sep,\n    dir = separator,\n    formatNew = (str) => `+ ${str}`,\n    formatOverwrite = (str) => `! ${str}`,\n    tab = '',\n  }: ToTreeOptions,\n) => {\n  if (dir[dir.length - 1] !== separator) {\n    dir += separator;\n  }\n  let subtree = ' (...)';\n  if (depth > 0) {\n    const list = fs.readdirSync(dir, { withFileTypes: true }) as IDirent[];\n    let actualFiles: Map<string, Dirent>;\n    try {\n      actualFiles = new Map(\n        nodeFs\n          .readdirSync(dir, { withFileTypes: true })\n          .map((entry) => [entry.name, entry]),\n      );\n    } catch {\n      actualFiles = new Map();\n    }\n    subtree = printTree(\n      tab,\n      list.map((entry) => (tab) => {\n        if (entry.isDirectory()) {\n          return toTree(fs, {\n            depth: depth - 1,\n            dir: `${dir}${entry.name}`,\n            formatNew,\n            formatOverwrite,\n            tab,\n          });\n        }\n        let formattedName: string;\n        let willBeOverwritten = false;\n        const willBeCreated = !actualFiles.has(`${entry.name}`);\n        if (!willBeCreated) {\n          const actualDirent = actualFiles.get(`${entry.name}`)!;\n          if (entry.isSymbolicLink()) {\n            if (!actualDirent.isSymbolicLink()) {\n              willBeOverwritten = true;\n            } else {\n              try {\n                const actualRealpath = nodeFs.realpathSync(\n                  path.join(dir, `${entry.name}`),\n                );\n                const realpath = fs.readlinkSync(\n                  path.join(dir, `${entry.name}`),\n                );\n                if (actualRealpath !== realpath) {\n                  willBeOverwritten = true;\n                }\n              } catch {\n                willBeOverwritten = true;\n              }\n            }\n          } else {\n            // implies file\n            if (!actualDirent.isFile()) {\n              willBeOverwritten = true;\n            } else {\n              try {\n                const actualStat = nodeFs.statSync(\n                  path.join(dir, `${entry.name}`),\n                );\n                const stat = fs.statSync(path.join(dir, `${entry.name}`));\n                if (actualStat.size !== stat.size) {\n                  willBeOverwritten = true;\n                }\n              } catch {\n                willBeOverwritten = true;\n              }\n            }\n          }\n        }\n        if (willBeOverwritten) {\n          formattedName = formatOverwrite(`${entry.name}`);\n        } else if (willBeCreated) {\n          formattedName = formatNew(`${entry.name}`);\n        } else {\n          // identical, hopefully\n          formattedName = `${entry.name}`;\n        }\n        if (entry.isSymbolicLink()) {\n          return `${formattedName} → ${fs.readlinkSync(path.join(dir, `${entry.name}`))}`;\n        } else {\n          return formattedName;\n        }\n      }),\n    );\n  }\n  const base = basename(dir, separator) + separator;\n  return base + subtree;\n};\n\nexport interface ToTreeOptions {\n  depth?: number;\n  dir?: string;\n  formatNew?: (str: string) => string;\n  formatOverwrite?: (str: string) => string;\n  separator?: typeof sep;\n  tab?: string;\n}\n"]}