UNPKG

fs-visitor

Version:

A Node.js library for recursively listing files and directories with customizable filtering and sorting options.

120 lines (116 loc) 3.49 kB
// src/index.ts import fs2 from "fs"; import path from "path"; // src/model.ts var assertConfig = ({ cwd = process.cwd(), deep = Infinity, relativePrefix = "", useSlash = true, withDirectory = false, asTree = false, filterEntry = [], sorter = (a, b) => { return a.level > b.level ? -1 : a.level < b.level ? 1 : 0; } } = {}) => { const filterEntryArray = Array.isArray(filterEntry) ? filterEntry : [filterEntry]; return { cwd, deep, relativePrefix, useSlash, asTree, withDirectory, filterEntry: filterEntryArray, sorter }; }; // src/utils.ts import fs from "fs"; var createErrorDirectory = (name) => () => { throw new Error(`Entry: ${name} is a directory`); }; var createReadFileSync = ({ type, name, absolute }) => { return type === "file" ? (opts) => fs.readFileSync(absolute, opts) : createErrorDirectory(name); }; var createWriteFileSync = ({ type, name, absolute }) => { return type === "file" ? (data, opts = {}) => fs.writeFileSync(absolute, data, opts) : createErrorDirectory(name); }; var createAppendFileSync = ({ type, name, absolute }) => { return type === "file" ? (data, opts = {}) => fs.writeFileSync(absolute, data, opts) : createErrorDirectory(name); }; // src/index.ts var processEntries = (parent, config, entryCallback) => { const nextLevel = parent.level + 1; if (nextLevel > config.deep) { return; } fs2.readdirSync(parent.absolute, { withFileTypes: true }).map((entry) => { const name = entry.name; const type = entry.isDirectory() ? "directory" : entry.isFile() ? "file" : ""; const absolute = path.join(parent.absolute, name); const relative = path.join(parent.relative, name); return { level: nextLevel, type, name, absolute, relative, children: [] }; }).map((current) => { if (config.useSlash) { current.absolute = current.absolute.replace(/\\/g, "/"); current.relative = current.relative.replace(/\\/g, "/"); } return current; }).filter((current) => { return current.type === "directory" || config.filterEntry.length === 0 || config.filterEntry.some((filterCallback) => filterCallback(current)); }).map((currentBase) => { return { ...currentBase, readFileSync: createReadFileSync(currentBase), writeFileSync: createWriteFileSync(currentBase), appendFileSync: createAppendFileSync(currentBase) }; }).forEach((current) => { if (current.type === "directory") { if (config.withDirectory || config.asTree) { entryCallback(current, parent); } processEntries(current, config, entryCallback); } else if (current.type === "file") { entryCallback(current, parent); } }); }; var processVisitor = (directory, opts = {}) => { const config = assertConfig(opts); const result = []; const errorRoot = createErrorDirectory("root"); const root = { level: 0, name: "", type: "directory", absolute: path.join(config.cwd, directory), relative: config.relativePrefix, children: [], appendFileSync: errorRoot, writeFileSync: errorRoot, readFileSync: errorRoot }; processEntries(root, config, (current, parent) => { if (config.asTree) { parent.children.push(current); } else { result.push(current); } }); return config.asTree ? [root] : result.sort(config.sorter); }; var src_default = processVisitor; export { src_default as default, processVisitor };