zephyr-agent
Version:
Zephyr plugin agent
152 lines (151 loc) • 4.99 kB
JavaScript
import "node:module";
import { readFile, readdir, realpath, stat } from "node:fs/promises";
import { join, resolve } from "node:path";
const SKIP_PATH_PATTERNS = [
/(^|\/)node_modules($|\/)/i,
/(^|\/)\.git($|\/)/i,
/(^|\/)\.DS_Store$/i,
/(^|\/)thumbs\.db$/i
];
async function readDirRecursive(dirPath, options = {}) {
const files = [];
for await (const file of resolveDir({
currentDir: resolve(dirPath),
relativePrefix: '',
readContents: false,
activeRealDirs: new Set(),
includeIgnoredPaths: options.includeIgnoredPaths ?? false,
failOnError: options.failOnError ?? false
}))files.push({
fullPath: file.fullPath,
relativePath: file.relativePath
});
return files;
}
async function readDirRecursiveWithContents(dirPath, options = {}) {
const files = [];
for await (const file of resolveDir({
currentDir: resolve(dirPath),
relativePrefix: '',
readContents: true,
activeRealDirs: new Set(),
includeIgnoredPaths: options.includeIgnoredPaths ?? false,
failOnError: options.failOnError ?? false
}))if (file.content) files.push(file);
return files;
}
async function* resolveDir({ currentDir, relativePrefix, readContents, activeRealDirs, includeIgnoredPaths, failOnError }) {
let entries;
try {
entries = await readdir(currentDir, {
withFileTypes: true
});
} catch (error) {
if (failOnError) throw error;
return;
}
const currentRealDir = await safeRealpath(currentDir, failOnError);
if (activeRealDirs.has(currentRealDir)) return;
activeRealDirs.add(currentRealDir);
try {
for (const entry of entries){
const fullPath = resolve(currentDir, entry.name);
const relativePath = relativePrefix ? join(relativePrefix, entry.name) : entry.name;
const normalizedRelativePath = normalizePath(relativePath);
if (!(!includeIgnoredPaths && shouldSkipRelativePath(normalizedRelativePath, entry))) yield* resolveFile({
fullPath,
relativePath,
entry,
readContents,
activeRealDirs,
includeIgnoredPaths,
failOnError
});
}
} finally{
activeRealDirs.delete(currentRealDir);
}
}
async function* resolveFile({ fullPath, relativePath, entry, readContents, activeRealDirs, includeIgnoredPaths, failOnError }) {
if (entry.isSymbolicLink()) return void (yield* resolveSymbolicLink({
fullPath,
relativePath,
readContents,
activeRealDirs,
includeIgnoredPaths,
failOnError
}));
if (entry.isDirectory()) return void (yield* resolveDir({
currentDir: fullPath,
relativePrefix: relativePath,
readContents,
activeRealDirs,
includeIgnoredPaths,
failOnError
}));
if (entry.isFile()) {
const content = readContents ? await safeReadFile(fullPath, failOnError) : void 0;
if (readContents && !content) return;
yield {
fullPath,
relativePath,
content
};
}
}
async function* resolveSymbolicLink({ fullPath, relativePath, readContents, activeRealDirs, includeIgnoredPaths, failOnError }) {
const realPath = await safeRealpath(fullPath, failOnError);
let realStat;
try {
realStat = await stat(realPath);
} catch (error) {
if (failOnError) throw error;
return;
}
if (realStat.isDirectory()) {
if (activeRealDirs.has(realPath)) return;
yield* resolveDir({
currentDir: realPath,
relativePrefix: relativePath,
readContents,
activeRealDirs,
includeIgnoredPaths,
failOnError
});
return;
}
if (realStat.isFile()) {
const content = readContents ? await safeReadFile(realPath, failOnError) : void 0;
if (readContents && !content) return;
yield {
fullPath: realPath,
relativePath,
content
};
}
}
async function safeReadFile(path, failOnError) {
try {
return await readFile(path);
} catch (error) {
if (failOnError) throw error;
return;
}
}
async function safeRealpath(path, failOnError) {
try {
return await realpath(path);
} catch (error) {
if (failOnError) throw error;
return path;
}
}
function normalizePath(filePath) {
return filePath.replace(/\\/g, '/');
}
function shouldSkipRelativePath(relativePath, entry) {
if (entry.isDirectory()) return SKIP_PATH_PATTERNS.some((pattern)=>pattern.test(`${relativePath}/`));
return SKIP_PATH_PATTERNS.some((pattern)=>pattern.test(relativePath));
}
export { readDirRecursive, readDirRecursiveWithContents };
//# sourceMappingURL=read-dir-recursive.mjs.map