|
|
|
|
|
var __create = Object.create; |
|
|
var __defProp = Object.defineProperty; |
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; |
|
|
var __getOwnPropNames = Object.getOwnPropertyNames; |
|
|
var __getProtoOf = Object.getPrototypeOf; |
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty; |
|
|
var __copyProps = (to, from, except, desc) => { |
|
|
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { |
|
|
key = keys[i]; |
|
|
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { |
|
|
get: ((k) => from[k]).bind(null, key), |
|
|
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable |
|
|
}); |
|
|
} |
|
|
return to; |
|
|
}; |
|
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { |
|
|
value: mod, |
|
|
enumerable: true |
|
|
}) : target, mod)); |
|
|
|
|
|
|
|
|
const path = __toESM(require("path")); |
|
|
const fs = __toESM(require("fs")); |
|
|
|
|
|
|
|
|
function cleanPath(path$1) { |
|
|
let normalized = (0, path.normalize)(path$1); |
|
|
if (normalized.length > 1 && normalized[normalized.length - 1] === path.sep) normalized = normalized.substring(0, normalized.length - 1); |
|
|
return normalized; |
|
|
} |
|
|
const SLASHES_REGEX = /[\\/]/g; |
|
|
function convertSlashes(path$1, separator) { |
|
|
return path$1.replace(SLASHES_REGEX, separator); |
|
|
} |
|
|
const WINDOWS_ROOT_DIR_REGEX = /^[a-z]:[\\/]$/i; |
|
|
function isRootDirectory(path$1) { |
|
|
return path$1 === "/" || WINDOWS_ROOT_DIR_REGEX.test(path$1); |
|
|
} |
|
|
function normalizePath(path$1, options) { |
|
|
const { resolvePaths, normalizePath: normalizePath$1, pathSeparator } = options; |
|
|
const pathNeedsCleaning = process.platform === "win32" && path$1.includes("/") || path$1.startsWith("."); |
|
|
if (resolvePaths) path$1 = (0, path.resolve)(path$1); |
|
|
if (normalizePath$1 || pathNeedsCleaning) path$1 = cleanPath(path$1); |
|
|
if (path$1 === ".") return ""; |
|
|
const needsSeperator = path$1[path$1.length - 1] !== pathSeparator; |
|
|
return convertSlashes(needsSeperator ? path$1 + pathSeparator : path$1, pathSeparator); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function joinPathWithBasePath(filename, directoryPath) { |
|
|
return directoryPath + filename; |
|
|
} |
|
|
function joinPathWithRelativePath(root, options) { |
|
|
return function(filename, directoryPath) { |
|
|
const sameRoot = directoryPath.startsWith(root); |
|
|
if (sameRoot) return directoryPath.slice(root.length) + filename; |
|
|
else return convertSlashes((0, path.relative)(root, directoryPath), options.pathSeparator) + options.pathSeparator + filename; |
|
|
}; |
|
|
} |
|
|
function joinPath(filename) { |
|
|
return filename; |
|
|
} |
|
|
function joinDirectoryPath(filename, directoryPath, separator) { |
|
|
return directoryPath + filename + separator; |
|
|
} |
|
|
function build$7(root, options) { |
|
|
const { relativePaths, includeBasePath } = options; |
|
|
return relativePaths && root ? joinPathWithRelativePath(root, options) : includeBasePath ? joinPathWithBasePath : joinPath; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function pushDirectoryWithRelativePath(root) { |
|
|
return function(directoryPath, paths) { |
|
|
paths.push(directoryPath.substring(root.length) || "."); |
|
|
}; |
|
|
} |
|
|
function pushDirectoryFilterWithRelativePath(root) { |
|
|
return function(directoryPath, paths, filters) { |
|
|
const relativePath = directoryPath.substring(root.length) || "."; |
|
|
if (filters.every((filter) => filter(relativePath, true))) paths.push(relativePath); |
|
|
}; |
|
|
} |
|
|
const pushDirectory = (directoryPath, paths) => { |
|
|
paths.push(directoryPath || "."); |
|
|
}; |
|
|
const pushDirectoryFilter = (directoryPath, paths, filters) => { |
|
|
const path$1 = directoryPath || "."; |
|
|
if (filters.every((filter) => filter(path$1, true))) paths.push(path$1); |
|
|
}; |
|
|
const empty$2 = () => {}; |
|
|
function build$6(root, options) { |
|
|
const { includeDirs, filters, relativePaths } = options; |
|
|
if (!includeDirs) return empty$2; |
|
|
if (relativePaths) return filters && filters.length ? pushDirectoryFilterWithRelativePath(root) : pushDirectoryWithRelativePath(root); |
|
|
return filters && filters.length ? pushDirectoryFilter : pushDirectory; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const pushFileFilterAndCount = (filename, _paths, counts, filters) => { |
|
|
if (filters.every((filter) => filter(filename, false))) counts.files++; |
|
|
}; |
|
|
const pushFileFilter = (filename, paths, _counts, filters) => { |
|
|
if (filters.every((filter) => filter(filename, false))) paths.push(filename); |
|
|
}; |
|
|
const pushFileCount = (_filename, _paths, counts, _filters) => { |
|
|
counts.files++; |
|
|
}; |
|
|
const pushFile = (filename, paths) => { |
|
|
paths.push(filename); |
|
|
}; |
|
|
const empty$1 = () => {}; |
|
|
function build$5(options) { |
|
|
const { excludeFiles, filters, onlyCounts } = options; |
|
|
if (excludeFiles) return empty$1; |
|
|
if (filters && filters.length) return onlyCounts ? pushFileFilterAndCount : pushFileFilter; |
|
|
else if (onlyCounts) return pushFileCount; |
|
|
else return pushFile; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const getArray = (paths) => { |
|
|
return paths; |
|
|
}; |
|
|
const getArrayGroup = () => { |
|
|
return [""].slice(0, 0); |
|
|
}; |
|
|
function build$4(options) { |
|
|
return options.group ? getArrayGroup : getArray; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const groupFiles = (groups, directory, files) => { |
|
|
groups.push({ |
|
|
directory, |
|
|
files, |
|
|
dir: directory |
|
|
}); |
|
|
}; |
|
|
const empty = () => {}; |
|
|
function build$3(options) { |
|
|
return options.group ? groupFiles : empty; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const resolveSymlinksAsync = function(path$1, state, callback$1) { |
|
|
const { queue, fs: fs$1, options: { suppressErrors } } = state; |
|
|
queue.enqueue(); |
|
|
fs$1.realpath(path$1, (error, resolvedPath) => { |
|
|
if (error) return queue.dequeue(suppressErrors ? null : error, state); |
|
|
fs$1.stat(resolvedPath, (error$1, stat) => { |
|
|
if (error$1) return queue.dequeue(suppressErrors ? null : error$1, state); |
|
|
if (stat.isDirectory() && isRecursive(path$1, resolvedPath, state)) return queue.dequeue(null, state); |
|
|
callback$1(stat, resolvedPath); |
|
|
queue.dequeue(null, state); |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
const resolveSymlinks = function(path$1, state, callback$1) { |
|
|
const { queue, fs: fs$1, options: { suppressErrors } } = state; |
|
|
queue.enqueue(); |
|
|
try { |
|
|
const resolvedPath = fs$1.realpathSync(path$1); |
|
|
const stat = fs$1.statSync(resolvedPath); |
|
|
if (stat.isDirectory() && isRecursive(path$1, resolvedPath, state)) return; |
|
|
callback$1(stat, resolvedPath); |
|
|
} catch (e) { |
|
|
if (!suppressErrors) throw e; |
|
|
} |
|
|
}; |
|
|
function build$2(options, isSynchronous) { |
|
|
if (!options.resolveSymlinks || options.excludeSymlinks) return null; |
|
|
return isSynchronous ? resolveSymlinks : resolveSymlinksAsync; |
|
|
} |
|
|
function isRecursive(path$1, resolved, state) { |
|
|
if (state.options.useRealPaths) return isRecursiveUsingRealPaths(resolved, state); |
|
|
let parent = (0, path.dirname)(path$1); |
|
|
let depth = 1; |
|
|
while (parent !== state.root && depth < 2) { |
|
|
const resolvedPath = state.symlinks.get(parent); |
|
|
const isSameRoot = !!resolvedPath && (resolvedPath === resolved || resolvedPath.startsWith(resolved) || resolved.startsWith(resolvedPath)); |
|
|
if (isSameRoot) depth++; |
|
|
else parent = (0, path.dirname)(parent); |
|
|
} |
|
|
state.symlinks.set(path$1, resolved); |
|
|
return depth > 1; |
|
|
} |
|
|
function isRecursiveUsingRealPaths(resolved, state) { |
|
|
return state.visited.includes(resolved + state.options.pathSeparator); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const onlyCountsSync = (state) => { |
|
|
return state.counts; |
|
|
}; |
|
|
const groupsSync = (state) => { |
|
|
return state.groups; |
|
|
}; |
|
|
const defaultSync = (state) => { |
|
|
return state.paths; |
|
|
}; |
|
|
const limitFilesSync = (state) => { |
|
|
return state.paths.slice(0, state.options.maxFiles); |
|
|
}; |
|
|
const onlyCountsAsync = (state, error, callback$1) => { |
|
|
report(error, callback$1, state.counts, state.options.suppressErrors); |
|
|
return null; |
|
|
}; |
|
|
const defaultAsync = (state, error, callback$1) => { |
|
|
report(error, callback$1, state.paths, state.options.suppressErrors); |
|
|
return null; |
|
|
}; |
|
|
const limitFilesAsync = (state, error, callback$1) => { |
|
|
report(error, callback$1, state.paths.slice(0, state.options.maxFiles), state.options.suppressErrors); |
|
|
return null; |
|
|
}; |
|
|
const groupsAsync = (state, error, callback$1) => { |
|
|
report(error, callback$1, state.groups, state.options.suppressErrors); |
|
|
return null; |
|
|
}; |
|
|
function report(error, callback$1, output, suppressErrors) { |
|
|
if (error && !suppressErrors) callback$1(error, output); |
|
|
else callback$1(null, output); |
|
|
} |
|
|
function build$1(options, isSynchronous) { |
|
|
const { onlyCounts, group, maxFiles } = options; |
|
|
if (onlyCounts) return isSynchronous ? onlyCountsSync : onlyCountsAsync; |
|
|
else if (group) return isSynchronous ? groupsSync : groupsAsync; |
|
|
else if (maxFiles) return isSynchronous ? limitFilesSync : limitFilesAsync; |
|
|
else return isSynchronous ? defaultSync : defaultAsync; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const readdirOpts = { withFileTypes: true }; |
|
|
const walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1) => { |
|
|
state.queue.enqueue(); |
|
|
if (currentDepth < 0) return state.queue.dequeue(null, state); |
|
|
const { fs: fs$1 } = state; |
|
|
state.visited.push(crawlPath); |
|
|
state.counts.directories++; |
|
|
fs$1.readdir(crawlPath || ".", readdirOpts, (error, entries = []) => { |
|
|
callback$1(entries, directoryPath, currentDepth); |
|
|
state.queue.dequeue(state.options.suppressErrors ? null : error, state); |
|
|
}); |
|
|
}; |
|
|
const walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1) => { |
|
|
const { fs: fs$1 } = state; |
|
|
if (currentDepth < 0) return; |
|
|
state.visited.push(crawlPath); |
|
|
state.counts.directories++; |
|
|
let entries = []; |
|
|
try { |
|
|
entries = fs$1.readdirSync(crawlPath || ".", readdirOpts); |
|
|
} catch (e) { |
|
|
if (!state.options.suppressErrors) throw e; |
|
|
} |
|
|
callback$1(entries, directoryPath, currentDepth); |
|
|
}; |
|
|
function build(isSynchronous) { |
|
|
return isSynchronous ? walkSync : walkAsync; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var Queue = class { |
|
|
count = 0; |
|
|
constructor(onQueueEmpty) { |
|
|
this.onQueueEmpty = onQueueEmpty; |
|
|
} |
|
|
enqueue() { |
|
|
this.count++; |
|
|
return this.count; |
|
|
} |
|
|
dequeue(error, output) { |
|
|
if (this.onQueueEmpty && (--this.count <= 0 || error)) { |
|
|
this.onQueueEmpty(error, output); |
|
|
if (error) { |
|
|
output.controller.abort(); |
|
|
this.onQueueEmpty = void 0; |
|
|
} |
|
|
} |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var Counter = class { |
|
|
_files = 0; |
|
|
_directories = 0; |
|
|
set files(num) { |
|
|
this._files = num; |
|
|
} |
|
|
get files() { |
|
|
return this._files; |
|
|
} |
|
|
set directories(num) { |
|
|
this._directories = num; |
|
|
} |
|
|
get directories() { |
|
|
return this._directories; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get dirs() { |
|
|
return this._directories; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var Aborter = class { |
|
|
aborted = false; |
|
|
abort() { |
|
|
this.aborted = true; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var Walker = class { |
|
|
root; |
|
|
isSynchronous; |
|
|
state; |
|
|
joinPath; |
|
|
pushDirectory; |
|
|
pushFile; |
|
|
getArray; |
|
|
groupFiles; |
|
|
resolveSymlink; |
|
|
walkDirectory; |
|
|
callbackInvoker; |
|
|
constructor(root, options, callback$1) { |
|
|
this.isSynchronous = !callback$1; |
|
|
this.callbackInvoker = build$1(options, this.isSynchronous); |
|
|
this.root = normalizePath(root, options); |
|
|
this.state = { |
|
|
root: isRootDirectory(this.root) ? this.root : this.root.slice(0, -1), |
|
|
paths: [""].slice(0, 0), |
|
|
groups: [], |
|
|
counts: new Counter(), |
|
|
options, |
|
|
queue: new Queue((error, state) => this.callbackInvoker(state, error, callback$1)), |
|
|
symlinks: new Map(), |
|
|
visited: [""].slice(0, 0), |
|
|
controller: new Aborter(), |
|
|
fs: options.fs || fs |
|
|
}; |
|
|
this.joinPath = build$7(this.root, options); |
|
|
this.pushDirectory = build$6(this.root, options); |
|
|
this.pushFile = build$5(options); |
|
|
this.getArray = build$4(options); |
|
|
this.groupFiles = build$3(options); |
|
|
this.resolveSymlink = build$2(options, this.isSynchronous); |
|
|
this.walkDirectory = build(this.isSynchronous); |
|
|
} |
|
|
start() { |
|
|
this.pushDirectory(this.root, this.state.paths, this.state.options.filters); |
|
|
this.walkDirectory(this.state, this.root, this.root, this.state.options.maxDepth, this.walk); |
|
|
return this.isSynchronous ? this.callbackInvoker(this.state, null) : null; |
|
|
} |
|
|
walk = (entries, directoryPath, depth) => { |
|
|
const { paths, options: { filters, resolveSymlinks: resolveSymlinks$1, excludeSymlinks, exclude, maxFiles, signal, useRealPaths, pathSeparator }, controller } = this.state; |
|
|
if (controller.aborted || signal && signal.aborted || maxFiles && paths.length > maxFiles) return; |
|
|
const files = this.getArray(this.state.paths); |
|
|
for (let i = 0; i < entries.length; ++i) { |
|
|
const entry = entries[i]; |
|
|
if (entry.isFile() || entry.isSymbolicLink() && !resolveSymlinks$1 && !excludeSymlinks) { |
|
|
const filename = this.joinPath(entry.name, directoryPath); |
|
|
this.pushFile(filename, files, this.state.counts, filters); |
|
|
} else if (entry.isDirectory()) { |
|
|
let path$1 = joinDirectoryPath(entry.name, directoryPath, this.state.options.pathSeparator); |
|
|
if (exclude && exclude(entry.name, path$1)) continue; |
|
|
this.pushDirectory(path$1, paths, filters); |
|
|
this.walkDirectory(this.state, path$1, path$1, depth - 1, this.walk); |
|
|
} else if (this.resolveSymlink && entry.isSymbolicLink()) { |
|
|
let path$1 = joinPathWithBasePath(entry.name, directoryPath); |
|
|
this.resolveSymlink(path$1, this.state, (stat, resolvedPath) => { |
|
|
if (stat.isDirectory()) { |
|
|
resolvedPath = normalizePath(resolvedPath, this.state.options); |
|
|
if (exclude && exclude(entry.name, useRealPaths ? resolvedPath : path$1 + pathSeparator)) return; |
|
|
this.walkDirectory(this.state, resolvedPath, useRealPaths ? resolvedPath : path$1 + pathSeparator, depth - 1, this.walk); |
|
|
} else { |
|
|
resolvedPath = useRealPaths ? resolvedPath : path$1; |
|
|
const filename = (0, path.basename)(resolvedPath); |
|
|
const directoryPath$1 = normalizePath((0, path.dirname)(resolvedPath), this.state.options); |
|
|
resolvedPath = this.joinPath(filename, directoryPath$1); |
|
|
this.pushFile(resolvedPath, files, this.state.counts, filters); |
|
|
} |
|
|
}); |
|
|
} |
|
|
} |
|
|
this.groupFiles(this.state.groups, directoryPath, files); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function promise(root, options) { |
|
|
return new Promise((resolve$1, reject) => { |
|
|
callback(root, options, (err, output) => { |
|
|
if (err) return reject(err); |
|
|
resolve$1(output); |
|
|
}); |
|
|
}); |
|
|
} |
|
|
function callback(root, options, callback$1) { |
|
|
let walker = new Walker(root, options, callback$1); |
|
|
walker.start(); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function sync(root, options) { |
|
|
const walker = new Walker(root, options); |
|
|
return walker.start(); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var APIBuilder = class { |
|
|
constructor(root, options) { |
|
|
this.root = root; |
|
|
this.options = options; |
|
|
} |
|
|
withPromise() { |
|
|
return promise(this.root, this.options); |
|
|
} |
|
|
withCallback(cb) { |
|
|
callback(this.root, this.options, cb); |
|
|
} |
|
|
sync() { |
|
|
return sync(this.root, this.options); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
let pm = null; |
|
|
|
|
|
try { |
|
|
require.resolve("picomatch"); |
|
|
pm = require("picomatch"); |
|
|
} catch {} |
|
|
var Builder = class { |
|
|
globCache = {}; |
|
|
options = { |
|
|
maxDepth: Infinity, |
|
|
suppressErrors: true, |
|
|
pathSeparator: path.sep, |
|
|
filters: [] |
|
|
}; |
|
|
globFunction; |
|
|
constructor(options) { |
|
|
this.options = { |
|
|
...this.options, |
|
|
...options |
|
|
}; |
|
|
this.globFunction = this.options.globFunction; |
|
|
} |
|
|
group() { |
|
|
this.options.group = true; |
|
|
return this; |
|
|
} |
|
|
withPathSeparator(separator) { |
|
|
this.options.pathSeparator = separator; |
|
|
return this; |
|
|
} |
|
|
withBasePath() { |
|
|
this.options.includeBasePath = true; |
|
|
return this; |
|
|
} |
|
|
withRelativePaths() { |
|
|
this.options.relativePaths = true; |
|
|
return this; |
|
|
} |
|
|
withDirs() { |
|
|
this.options.includeDirs = true; |
|
|
return this; |
|
|
} |
|
|
withMaxDepth(depth) { |
|
|
this.options.maxDepth = depth; |
|
|
return this; |
|
|
} |
|
|
withMaxFiles(limit) { |
|
|
this.options.maxFiles = limit; |
|
|
return this; |
|
|
} |
|
|
withFullPaths() { |
|
|
this.options.resolvePaths = true; |
|
|
this.options.includeBasePath = true; |
|
|
return this; |
|
|
} |
|
|
withErrors() { |
|
|
this.options.suppressErrors = false; |
|
|
return this; |
|
|
} |
|
|
withSymlinks({ resolvePaths = true } = {}) { |
|
|
this.options.resolveSymlinks = true; |
|
|
this.options.useRealPaths = resolvePaths; |
|
|
return this.withFullPaths(); |
|
|
} |
|
|
withAbortSignal(signal) { |
|
|
this.options.signal = signal; |
|
|
return this; |
|
|
} |
|
|
normalize() { |
|
|
this.options.normalizePath = true; |
|
|
return this; |
|
|
} |
|
|
filter(predicate) { |
|
|
this.options.filters.push(predicate); |
|
|
return this; |
|
|
} |
|
|
onlyDirs() { |
|
|
this.options.excludeFiles = true; |
|
|
this.options.includeDirs = true; |
|
|
return this; |
|
|
} |
|
|
exclude(predicate) { |
|
|
this.options.exclude = predicate; |
|
|
return this; |
|
|
} |
|
|
onlyCounts() { |
|
|
this.options.onlyCounts = true; |
|
|
return this; |
|
|
} |
|
|
crawl(root) { |
|
|
return new APIBuilder(root || ".", this.options); |
|
|
} |
|
|
withGlobFunction(fn) { |
|
|
this.globFunction = fn; |
|
|
return this; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
crawlWithOptions(root, options) { |
|
|
this.options = { |
|
|
...this.options, |
|
|
...options |
|
|
}; |
|
|
return new APIBuilder(root || ".", this.options); |
|
|
} |
|
|
glob(...patterns) { |
|
|
if (this.globFunction) return this.globWithOptions(patterns); |
|
|
return this.globWithOptions(patterns, ...[{ dot: true }]); |
|
|
} |
|
|
globWithOptions(patterns, ...options) { |
|
|
const globFn = this.globFunction || pm; |
|
|
|
|
|
if (!globFn) throw new Error("Please specify a glob function to use glob matching."); |
|
|
var isMatch = this.globCache[patterns.join("\0")]; |
|
|
if (!isMatch) { |
|
|
isMatch = globFn(patterns, ...options); |
|
|
this.globCache[patterns.join("\0")] = isMatch; |
|
|
} |
|
|
this.options.filters.push((path$1) => isMatch(path$1)); |
|
|
return this; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
exports.fdir = Builder; |