var fs = require('fs');
var path = require('path');
var merge2 = require('merge2');
var fastGlob = require('fast-glob');
var dirGlob = require('dir-glob');
var process = require('process');
var gitIgnore = require('ignore');
var slash = require('slash');
var node_url = require('url');
var node_stream = require('stream');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var fs__default = /*#__PURE__*/_interopDefault(fs);
var path__default = /*#__PURE__*/_interopDefault(path);
var merge2__default = /*#__PURE__*/_interopDefault(merge2);
var fastGlob__default = /*#__PURE__*/_interopDefault(fastGlob);
var dirGlob__default = /*#__PURE__*/_interopDefault(dirGlob);
var process__default = /*#__PURE__*/_interopDefault(process);
var gitIgnore__default = /*#__PURE__*/_interopDefault(gitIgnore);
var slash__default = /*#__PURE__*/_interopDefault(slash);
const toPath = urlOrPath => urlOrPath instanceof URL ? node_url.fileURLToPath(urlOrPath) : urlOrPath;
class FilterStream extends node_stream.Transform {
constructor(filter) {
super({
objectMode: true,
transform(data, encoding, callback) {
callback(undefined, filter(data) ? data : undefined);
},
});
}
}
const isNegativePattern = pattern => pattern[0] === '!';
const ignoreFilesGlobOptions = {
ignore: [
'**/node_modules',
'**/flow-typed',
'**/coverage',
'**/.git',
],
absolute: true,
dot: true,
};
const GITIGNORE_FILES_PATTERN = '**/.gitignore';
const applyBaseToPattern = (pattern, base) => isNegativePattern(pattern)
? '!' + path__default.default.posix.join(base, pattern.slice(1))
: path__default.default.posix.join(base, pattern);
const parseIgnoreFile = (file, cwd) => {
const base = slash__default.default(path__default.default.relative(cwd, path__default.default.dirname(file.filePath)));
return file.content
.split(/\r?\n/)
.filter(line => line && !line.startsWith('#'))
.map(pattern => applyBaseToPattern(pattern, base));
};
const toRelativePath = (fileOrDirectory, cwd) => {
cwd = slash__default.default(cwd);
if (path__default.default.isAbsolute(fileOrDirectory)) {
if (slash__default.default(fileOrDirectory).startsWith(cwd)) {
return path__default.default.relative(cwd, fileOrDirectory);
}
throw new Error(`Path ${fileOrDirectory} is not in cwd ${cwd}`);
}
return fileOrDirectory;
};
const getIsIgnoredPredicate = (files, cwd) => {
const patterns = files.flatMap(file => parseIgnoreFile(file, cwd));
const ignores = gitIgnore__default.default().add(patterns);
return fileOrDirectory => {
fileOrDirectory = toPath(fileOrDirectory);
fileOrDirectory = toRelativePath(fileOrDirectory, cwd);
return fileOrDirectory ? ignores.ignores(slash__default.default(fileOrDirectory)) : false;
};
};
const normalizeOptions$1 = (options = {}) => ({
cwd: toPath(options.cwd) || process__default.default.cwd(),
});
const isIgnoredByIgnoreFiles = async (patterns, options) => {
const {cwd} = normalizeOptions$1(options);
const paths = await fastGlob__default.default(patterns, {cwd, ...ignoreFilesGlobOptions});
const files = await Promise.all(
paths.map(async filePath => ({
filePath,
content: await fs__default.default.promises.readFile(filePath, 'utf8'),
})),
);
return getIsIgnoredPredicate(files, cwd);
};
const isIgnoredByIgnoreFilesSync = (patterns, options) => {
const {cwd} = normalizeOptions$1(options);
const paths = fastGlob__default.default.sync(patterns, {cwd, ...ignoreFilesGlobOptions});
const files = paths.map(filePath => ({
filePath,
content: fs__default.default.readFileSync(filePath, 'utf8'),
}));
return getIsIgnoredPredicate(files, cwd);
};
const isGitIgnored = options => isIgnoredByIgnoreFiles(GITIGNORE_FILES_PATTERN, options);
const isGitIgnoredSync = options => isIgnoredByIgnoreFilesSync(GITIGNORE_FILES_PATTERN, options);
const assertPatternsInput = patterns => {
if (patterns.some(pattern => typeof pattern !== 'string')) {
throw new TypeError('Patterns must be a string or an array of strings');
}
};
const toPatternsArray = patterns => {
patterns = [...new Set([patterns].flat())];
assertPatternsInput(patterns);
return patterns;
};
const checkCwdOption = options => {
if (!options.cwd) {
return;
}
let stat;
try {
stat = fs__default.default.statSync(options.cwd);
} catch {
return;
}
if (!stat.isDirectory()) {
throw new Error('The `cwd` option must be a path to a directory');
}
};
const normalizeOptions = (options = {}) => {
options = {
ignore: [],
expandDirectories: true,
...options,
cwd: toPath(options.cwd),
};
checkCwdOption(options);
return options;
};
const normalizeArguments = fn => async (patterns, options) => fn(toPatternsArray(patterns), normalizeOptions(options));
const normalizeArgumentsSync = fn => (patterns, options) => fn(toPatternsArray(patterns), normalizeOptions(options));
const getIgnoreFilesPatterns = options => {
const {ignoreFiles, gitignore} = options;
const patterns = ignoreFiles ? toPatternsArray(ignoreFiles) : [];
if (gitignore) {
patterns.push(GITIGNORE_FILES_PATTERN);
}
return patterns;
};
const getFilter = async options => {
const ignoreFilesPatterns = getIgnoreFilesPatterns(options);
return createFilterFunction(
ignoreFilesPatterns.length > 0 && await isIgnoredByIgnoreFiles(ignoreFilesPatterns, {cwd: options.cwd}),
);
};
const getFilterSync = options => {
const ignoreFilesPatterns = getIgnoreFilesPatterns(options);
return createFilterFunction(
ignoreFilesPatterns.length > 0 && isIgnoredByIgnoreFilesSync(ignoreFilesPatterns, {cwd: options.cwd}),
);
};
const createFilterFunction = isIgnored => {
const seen = new Set();
return fastGlobResult => {
const path = fastGlobResult.path || fastGlobResult;
const pathKey = path__default.default.normalize(path);
const seenOrIgnored = seen.has(pathKey) || (isIgnored && isIgnored(path));
seen.add(pathKey);
return !seenOrIgnored;
};
};
const unionFastGlobResults = (results, filter) => results.flat().filter(fastGlobResult => filter(fastGlobResult));
const unionFastGlobStreams = (streams, filter) => merge2__default.default(streams).pipe(new FilterStream(fastGlobResult => filter(fastGlobResult)));
const convertNegativePatterns = (patterns, options) => {
const tasks = [];
while (patterns.length > 0) {
const index = patterns.findIndex(pattern => isNegativePattern(pattern));
if (index === -1) {
tasks.push({patterns, options});
break;
}
const ignorePattern = patterns[index].slice(1);
for (const task of tasks) {
task.options.ignore.push(ignorePattern);
}
if (index !== 0) {
tasks.push({
patterns: patterns.slice(0, index),
options: {
...options,
ignore: [
...options.ignore,
ignorePattern,
],
},
});
}
patterns = patterns.slice(index + 1);
}
return tasks;
};
const getDirGlobOptions = (options, cwd) => ({
...(cwd ? {cwd} : {}),
...(Array.isArray(options) ? {files: options} : options),
});
const generateTasks = async (patterns, options) => {
const globTasks = convertNegativePatterns(patterns, options);
const {cwd, expandDirectories} = options;
if (!expandDirectories) {
return globTasks;
}
const patternExpandOptions = getDirGlobOptions(expandDirectories, cwd);
const ignoreExpandOptions = cwd ? {cwd} : undefined;
return Promise.all(
globTasks.map(async task => {
let {patterns, options} = task;
[
patterns,
options.ignore,
] = await Promise.all([
dirGlob__default.default(patterns, patternExpandOptions),
dirGlob__default.default(options.ignore, ignoreExpandOptions),
]);
return {patterns, options};
}),
);
};
const generateTasksSync = (patterns, options) => {
const globTasks = convertNegativePatterns(patterns, options);
const {cwd, expandDirectories} = options;
if (!expandDirectories) {
return globTasks;
}
const patternExpandOptions = getDirGlobOptions(expandDirectories, cwd);
const ignoreExpandOptions = cwd ? {cwd} : undefined;
return globTasks.map(task => {
let {patterns, options} = task;
patterns = dirGlob__default.default.sync(patterns, patternExpandOptions);
options.ignore = dirGlob__default.default.sync(options.ignore, ignoreExpandOptions);
return {patterns, options};
});
};
const globby = normalizeArguments(async (patterns, options) => {
const [
tasks,
filter,
] = await Promise.all([
generateTasks(patterns, options),
getFilter(options),
]);
const results = await Promise.all(tasks.map(task => fastGlob__default.default(task.patterns, task.options)));
return unionFastGlobResults(results, filter);
});
const globbySync = normalizeArgumentsSync((patterns, options) => {
const tasks = generateTasksSync(patterns, options);
const filter = getFilterSync(options);
const results = tasks.map(task => fastGlob__default.default.sync(task.patterns, task.options));
return unionFastGlobResults(results, filter);
});
const globbyStream = normalizeArgumentsSync((patterns, options) => {
const tasks = generateTasksSync(patterns, options);
const filter = getFilterSync(options);
const streams = tasks.map(task => fastGlob__default.default.stream(task.patterns, task.options));
return unionFastGlobStreams(streams, filter);
});
const isDynamicPattern = normalizeArgumentsSync(
(patterns, options) => patterns.some(pattern => fastGlob__default.default.isDynamicPattern(pattern, options)),
);
const generateGlobTasks = normalizeArguments(generateTasks);
const generateGlobTasksSync = normalizeArgumentsSync(generateTasksSync);
exports.generateGlobTasks = generateGlobTasks;
exports.generateGlobTasksSync = generateGlobTasksSync;
exports.globby = globby;
exports.globbyStream = globbyStream;
exports.globbySync = globbySync;
exports.isDynamicPattern = isDynamicPattern;
exports.isGitIgnored = isGitIgnored;
exports.isGitIgnoredSync = isGitIgnoredSync;
|