bws-secure
Version:
Secure environment management with Bitwarden Secrets Manager
96 lines (83 loc) • 2.82 kB
JavaScript
import { readdir } from 'node:fs/promises';
import { join, resolve, sep, posix } from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = fileURLToPath(new URL('.', import.meta.url));
/**
* Normalize path separators to forward slashes for consistency across platforms
* @param {string} path - Path to normalize
* @returns {string} - Normalized path
*/
function normalizePath(path) {
return path.split(sep).join(posix.sep);
}
/**
* Recursively walks through directories and returns matching files
* @param {string} dir - Directory to start from
* @param {object} options - Configuration options
* @param {string[]} options.ignore - Patterns to ignore
* @param {RegExp} options.pattern - Pattern to match against
* @returns {Promise<string[]>} - Array of matching file paths
*/
export async function walkDir(dir, options = {}) {
const { ignore = [], pattern = null } = options;
const files = [];
async function walk(currentDir) {
const entries = await readdir(currentDir, { withFileTypes: true });
for (const entry of entries) {
const path = normalizePath(join(currentDir, entry.name));
// Check ignore patterns
if (ignore.some((pattern) => normalizePath(path).includes(pattern))) {
continue;
}
if (entry.isDirectory()) {
await walk(path);
} else if (entry.isFile()) {
if (!pattern || pattern.test(normalizePath(path))) {
files.push(path);
}
}
}
}
await walk(resolve(dir));
return files;
}
/**
* Converts a glob-like pattern to RegExp, handling platform-specific paths
* @param {string} pattern - Glob-like pattern
* @returns {RegExp} - Regular expression
*/
export function patternToRegExp(pattern) {
const normalizedPattern = normalizePath(pattern);
return new RegExp(
normalizedPattern
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
.replace(/\*\*/g, '___GLOBSTAR___')
.replace(/\*/g, '[^/]*')
.replace(/\?/g, '.')
.replace(/___GLOBSTAR___/g, '.*')
);
}
/**
* Find files matching a pattern
* @param {string} pattern - Glob-like pattern
* @param {object} options - Search options
* @param {string} options.cwd - Working directory
* @param {string[]} options.ignore - Patterns to ignore
* @returns {Promise<string[]>} - Matching files
*/
export async function findFiles(pattern, options = {}) {
const regex = patternToRegExp(pattern);
const cwd = options.cwd || process.cwd();
try {
const files = await walkDir(cwd, {
...options,
pattern: regex
});
// Return paths relative to cwd for consistency
return files.map((file) => normalizePath(file));
} catch (error) {
console.error('Error finding files:', error);
return [];
}
}