Socket
Socket
Sign inDemoInstall

globby

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

globby - npm Package Compare versions

Comparing version 12.2.0 to 13.0.0

utilities.js

72

gitignore.js

@@ -7,10 +7,13 @@ import process from 'node:process';

import slash from 'slash';
import toPath from './to-path.js';
import {toPath} from './utilities.js';
const DEFAULT_IGNORE = [
'**/node_modules/**',
'**/flow-typed/**',
'**/coverage/**',
'**/.git',
];
const gitignoreGlobOptions = {
ignore: [
'**/node_modules',
'**/flow-typed',
'**/coverage',
'**/.git',
],
absolute: true,
};

@@ -60,51 +63,40 @@ const mapGitIgnorePatternTo = base => ignore => {

const getIsIgnoredPredicate = (ignores, cwd) => p => ignores.ignores(slash(path.relative(cwd, ensureAbsolutePathForCwd(cwd, toPath(p.path || p)))));
const getIsIgnoredPredicate = (ignores, cwd) => p => ignores.ignores(slash(path.relative(cwd, ensureAbsolutePathForCwd(cwd, toPath(p)))));
const getFile = async (file, cwd) => {
const filePath = path.join(cwd, file);
const content = await fs.promises.readFile(filePath, 'utf8');
const getFile = async (filePath, cwd) => ({
cwd,
filePath,
content: await fs.promises.readFile(filePath, 'utf8'),
});
return {
cwd,
filePath,
content,
};
};
const getFileSync = (filePath, cwd) => ({
cwd,
filePath,
content: fs.readFileSync(filePath, 'utf8'),
});
const getFileSync = (file, cwd) => {
const filePath = path.join(cwd, file);
const content = fs.readFileSync(filePath, 'utf8');
const normalizeOptions = (options = {}) => ({
cwd: toPath(options.cwd) || slash(process.cwd()),
});
return {
cwd,
filePath,
content,
};
};
const normalizeOptions = ({
ignore = [],
cwd = slash(process.cwd()),
} = {}) => ({ignore: [...DEFAULT_IGNORE, ...ignore], cwd: toPath(cwd)});
export const isGitIgnored = async options => {
options = normalizeOptions(options);
const {cwd} = normalizeOptions(options);
const paths = await fastGlob('**/.gitignore', options);
const paths = await fastGlob('**/.gitignore', {cwd, ...gitignoreGlobOptions});
const files = await Promise.all(paths.map(file => getFile(file, options.cwd)));
const files = await Promise.all(paths.map(file => getFile(file, cwd)));
const ignores = reduceIgnore(files);
return getIsIgnoredPredicate(ignores, options.cwd);
return getIsIgnoredPredicate(ignores, cwd);
};
export const isGitIgnoredSync = options => {
options = normalizeOptions(options);
const {cwd} = normalizeOptions(options);
const paths = fastGlob.sync('**/.gitignore', options);
const paths = fastGlob.sync('**/.gitignore', {cwd, ...gitignoreGlobOptions});
const files = paths.map(file => getFileSync(file, options.cwd));
const files = paths.map(file => getFileSync(file, cwd));
const ignores = reduceIgnore(files);
return getIsIgnoredPredicate(ignores, options.cwd);
return getIsIgnoredPredicate(ignores, cwd);
};

@@ -7,3 +7,3 @@ import {URL} from 'node:url'; // TODO: Remove this when https://github.com/DefinitelyTyped/DefinitelyTyped/issues/34960 is fixed.

export interface GlobTask {
readonly pattern: string;
readonly patterns: string[];
readonly options: Options;

@@ -61,3 +61,2 @@ }

readonly cwd?: URL | string;
readonly ignore?: readonly string[];
}

@@ -146,2 +145,12 @@

options?: Options
): Promise<GlobTask[]>;
/**
@see generateGlobTasks
@returns An object in the format `{pattern: string, options: object}`, which can be passed as arguments to [`fast-glob`](https://github.com/mrmlnc/fast-glob). This is useful for other globbing-related packages.
*/
export function generateGlobTasksSync(
patterns: string | readonly string[],
options?: Options
): GlobTask[];

@@ -148,0 +157,0 @@

import fs from 'node:fs';
import arrayUnion from 'array-union';
import merge2 from 'merge2';
import fastGlob from 'fast-glob';
import dirGlob from 'dir-glob';
import toPath from './to-path.js';
import {isGitIgnored, isGitIgnoredSync} from './gitignore.js';
import {FilterStream, UniqueStream} from './stream-utils.js';
import {FilterStream, toPath} from './utilities.js';
const DEFAULT_FILTER = () => false;
const isNegative = pattern => pattern[0] === '!';

@@ -20,2 +16,8 @@

const toPatternsArray = patterns => {
patterns = [...new Set([patterns].flat())];
assertPatternsInput(patterns);
return patterns;
};
const checkCwdOption = options => {

@@ -38,159 +40,166 @@ if (!options.cwd) {

const getPathString = p => p.stats instanceof fs.Stats ? p.path : p;
export const generateGlobTasks = (patterns, taskOptions = {}) => {
patterns = arrayUnion([patterns].flat());
assertPatternsInput(patterns);
const globTasks = [];
taskOptions = {
const normalizeOptions = (options = {}) => {
options = {
ignore: [],
expandDirectories: true,
...taskOptions,
cwd: toPath(taskOptions.cwd),
...options,
cwd: toPath(options.cwd),
};
checkCwdOption(taskOptions);
checkCwdOption(options);
for (const [index, pattern] of patterns.entries()) {
if (isNegative(pattern)) {
continue;
}
return options;
};
const ignore = patterns
.slice(index)
.filter(pattern => isNegative(pattern))
.map(pattern => pattern.slice(1));
const normalizeArguments = fn => async (patterns, options) => fn(toPatternsArray(patterns), normalizeOptions(options));
const normalizeArgumentsSync = fn => (patterns, options) => fn(toPatternsArray(patterns), normalizeOptions(options));
const options = {
...taskOptions,
ignore: [...taskOptions.ignore, ...ignore],
};
const getFilter = async options => createFilterFunction(
options.gitignore && await isGitIgnored({cwd: options.cwd}),
);
globTasks.push({pattern, options});
}
const getFilterSync = options => createFilterFunction(
options.gitignore && isGitIgnoredSync({cwd: options.cwd}),
);
return globTasks;
const createFilterFunction = isIgnored => {
const seen = new Set();
return fastGlobResult => {
const path = fastGlobResult.path || fastGlobResult;
const seenOrIgnored = seen.has(path) || (isIgnored && isIgnored(path));
seen.add(path);
return !seenOrIgnored;
};
};
const globDirectories = (task, fn) => {
let options = {};
if (task.options.cwd) {
options.cwd = task.options.cwd;
}
const unionFastGlobResults = (results, filter) => results.flat().filter(fastGlobResult => filter(fastGlobResult));
const unionFastGlobStreams = (streams, filter) => merge2(streams).pipe(new FilterStream(fastGlobResult => filter(fastGlobResult)));
if (Array.isArray(task.options.expandDirectories)) {
options = {
...options,
files: task.options.expandDirectories,
};
} else if (typeof task.options.expandDirectories === 'object') {
options = {
...options,
...task.options.expandDirectories,
};
}
const convertNegativePatterns = (patterns, options) => {
const tasks = [];
return fn(task.pattern, options);
};
while (patterns.length > 0) {
const index = patterns.findIndex(pattern => isNegative(pattern));
const getPattern = (task, fn) => task.options.expandDirectories ? globDirectories(task, fn) : [task.pattern];
if (index === -1) {
tasks.push({patterns, options});
break;
}
const getFilterSync = options => options && options.gitignore
? isGitIgnoredSync({cwd: options.cwd, ignore: options.ignore})
: DEFAULT_FILTER;
const ignorePattern = patterns[index].slice(1);
const globToTask = task => async glob => {
const {options} = task;
if (options.ignore && Array.isArray(options.ignore) && options.expandDirectories) {
options.ignore = await dirGlob(options.ignore);
}
for (const task of tasks) {
task.options.ignore.push(ignorePattern);
}
return {
pattern: glob,
options,
};
};
if (index !== 0) {
tasks.push({
patterns: patterns.slice(0, index),
options: {
...options,
ignore: [
...options.ignore,
ignorePattern,
],
},
});
}
const globToTaskSync = task => glob => {
const {options} = task;
if (options.ignore && Array.isArray(options.ignore) && options.expandDirectories) {
options.ignore = dirGlob.sync(options.ignore);
patterns = patterns.slice(index + 1);
}
return {
pattern: glob,
options,
};
return tasks;
};
export const globby = async (patterns, options) => {
const globTasks = generateGlobTasks(patterns, options);
const getDirGlobOptions = (options, cwd) => ({
...(cwd ? {cwd} : {}),
...(Array.isArray(options) ? {files: options} : options),
});
const getFilter = async () => options && options.gitignore
? isGitIgnored({cwd: options.cwd, ignore: options.ignore})
: DEFAULT_FILTER;
const generateTasks = async (patterns, options) => {
const globTasks = convertNegativePatterns(patterns, options);
const getTasks = async () => {
const tasks = await Promise.all(globTasks.map(async task => {
const globs = await getPattern(task, dirGlob);
return Promise.all(globs.map(globToTask(task)));
}));
const {cwd, expandDirectories} = options;
return arrayUnion(...tasks);
};
if (!expandDirectories) {
return globTasks;
}
const [filter, tasks] = await Promise.all([getFilter(), getTasks()]);
const paths = await Promise.all(tasks.map(task => fastGlob(task.pattern, task.options)));
const patternExpandOptions = getDirGlobOptions(expandDirectories, cwd);
const ignoreExpandOptions = cwd ? {cwd} : undefined;
return arrayUnion(...paths).filter(path_ => !filter(getPathString(path_)));
return Promise.all(
globTasks.map(async task => {
let {patterns, options} = task;
[
patterns,
options.ignore,
] = await Promise.all([
dirGlob(patterns, patternExpandOptions),
dirGlob(options.ignore, ignoreExpandOptions),
]);
return {patterns, options};
}),
);
};
export const globbySync = (patterns, options) => {
const globTasks = generateGlobTasks(patterns, options);
const generateTasksSync = (patterns, options) => {
const globTasks = convertNegativePatterns(patterns, options);
const tasks = [];
for (const task of globTasks) {
const newTask = getPattern(task, dirGlob.sync).map(globToTaskSync(task));
tasks.push(...newTask);
const {cwd, expandDirectories} = options;
if (!expandDirectories) {
return globTasks;
}
const filter = getFilterSync(options);
const patternExpandOptions = getDirGlobOptions(expandDirectories, cwd);
const ignoreExpandOptions = cwd ? {cwd} : undefined;
let matches = [];
for (const task of tasks) {
matches = arrayUnion(matches, fastGlob.sync(task.pattern, task.options));
}
return matches.filter(path_ => !filter(path_));
return globTasks.map(task => {
let {patterns, options} = task;
patterns = dirGlob.sync(patterns, patternExpandOptions);
options.ignore = dirGlob.sync(options.ignore, ignoreExpandOptions);
return {patterns, options};
});
};
export const globbyStream = (patterns, options) => {
const globTasks = generateGlobTasks(patterns, options);
export 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(task.patterns, task.options)));
const tasks = [];
for (const task of globTasks) {
const newTask = getPattern(task, dirGlob.sync).map(globToTaskSync(task));
tasks.push(...newTask);
}
return unionFastGlobResults(results, filter);
});
export const globbySync = normalizeArgumentsSync((patterns, options) => {
const tasks = generateTasksSync(patterns, options);
const filter = getFilterSync(options);
const filterStream = new FilterStream(p => !filter(p));
const uniqueStream = new UniqueStream();
const results = tasks.map(task => fastGlob.sync(task.patterns, task.options));
return merge2(tasks.map(task => fastGlob.stream(task.pattern, task.options)))
.pipe(filterStream)
.pipe(uniqueStream);
};
return unionFastGlobResults(results, filter);
});
export const isDynamicPattern = (patterns, options = {}) => {
options = {
...options,
cwd: toPath(options.cwd),
};
export const globbyStream = normalizeArgumentsSync((patterns, options) => {
const tasks = generateTasksSync(patterns, options);
const filter = getFilterSync(options);
const streams = tasks.map(task => fastGlob.stream(task.patterns, task.options));
return [patterns].flat().some(pattern => fastGlob.isDynamicPattern(pattern, options));
};
return unionFastGlobStreams(streams, filter);
});
export const isDynamicPattern = normalizeArgumentsSync(
(patterns, options) => patterns.some(pattern => fastGlob.isDynamicPattern(pattern, options)),
);
export const generateGlobTasks = normalizeArguments(generateTasks);
export const generateGlobTasksSync = normalizeArgumentsSync(generateTasksSync);
export {

@@ -197,0 +206,0 @@ isGitIgnored,

{
"name": "globby",
"version": "12.2.0",
"version": "13.0.0",
"description": "User-friendly glob matching",

@@ -19,3 +19,3 @@ "license": "MIT",

"scripts": {
"bench": "npm update glob-stream fast-glob && matcha bench.js",
"bench": "npm update @globby/main-branch glob-stream fast-glob && node bench.js",
"test": "xo && ava && tsd"

@@ -27,4 +27,3 @@ },

"gitignore.js",
"stream-utils.js",
"to-path.js"
"utilities.js"
],

@@ -65,6 +64,5 @@ "keywords": [

"dependencies": {
"array-union": "^3.0.1",
"dir-glob": "^3.0.1",
"fast-glob": "^3.2.7",
"ignore": "^5.1.9",
"fast-glob": "^3.2.11",
"ignore": "^5.2.0",
"merge2": "^1.4.1",

@@ -74,11 +72,11 @@ "slash": "^4.0.0"

"devDependencies": {
"@types/node": "^16.11.11",
"ava": "^3.15.0",
"@globby/main-branch": "sindresorhus/globby#main",
"@types/node": "^17.0.10",
"ava": "^4.0.1",
"benchmark": "2.1.4",
"get-stream": "^6.0.1",
"glob-stream": "^7.0.0",
"globby": "sindresorhus/globby#main",
"matcha": "^0.7.0",
"rimraf": "^3.0.2",
"tsd": "^0.19.0",
"typescript": "^4.5.2",
"tsd": "^0.19.1",
"typescript": "^4.5.5",
"xo": "^0.47.0"

@@ -90,3 +88,9 @@ },

]
},
"ava": {
"files": [
"!tests/utilities.js"
],
"workerThreads": false
}
}

@@ -113,6 +113,12 @@ # globby

Returns an `object[]` in the format `{pattern: string, options: Object}`, which can be passed as arguments to [`fast-glob`](https://github.com/mrmlnc/fast-glob). This is useful for other globbing-related packages.
Returns an `Promise<object[]>` in the format `{patterns: string[], options: Object}`, which can be passed as arguments to [`fast-glob`](https://github.com/mrmlnc/fast-glob). This is useful for other globbing-related packages.
Note that you should avoid running the same tasks multiple times as they contain a file system cache. Instead, run this method each time to ensure file system changes are taken into consideration.
### generateGlobTasksSync(patterns, options?)
Returns an `object[]` in the format `{patterns: string[], options: Object}`, which can be passed as arguments to [`fast-glob`](https://github.com/mrmlnc/fast-glob). This is useful for other globbing-related packages.
Takes the same arguments as `generateGlobTasks`.
### isDynamicPattern(patterns, options?)

@@ -130,3 +136,3 @@

Takes `cwd?: URL | string` and `ignore?: string[]` as options. `.gitignore` files matched by the ignore config are not used for the resulting filter function.
Takes `cwd?: URL | string` as options.

@@ -145,3 +151,3 @@ ```js

Takes the same options as `isGitIgnored`.
Takes `cwd?: URL | string` as options.

@@ -148,0 +154,0 @@ ## Globbing patterns

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc