Skip to content

Commit 5c32b4a

Browse files
authoredJul 22, 2021
Require Node.js 12.20 and move to ESM (#181)
1 parent 94e192c commit 5c32b4a

11 files changed

+347
-334
lines changed
 

‎.github/workflows/main.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
node-version:
13+
- 16
1314
- 14
1415
- 12
15-
- 10
1616
os:
1717
- ubuntu-latest
1818
- macos-latest
1919
- windows-latest
2020
steps:
2121
- uses: actions/checkout@v2
22-
- uses: actions/setup-node@v1
22+
- uses: actions/setup-node@v2
2323
with:
2424
node-version: ${{ matrix.node-version }}
2525
- run: npm install

‎bench.js

+37-32
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,100 @@
1-
'use strict';
21
/* global after, before, bench, suite */
3-
const fs = require('fs');
4-
const rimraf = require('rimraf');
5-
const globbyMainBranch = require('globby');
6-
const gs = require('glob-stream');
7-
const fastGlob = require('fast-glob');
8-
const globby = require('.');
2+
import fs from 'node:fs';
3+
import path from 'node:path';
4+
import {fileURLToPath} from 'node:url';
5+
import rimraf from 'rimraf';
6+
import globbyMainBranch from 'globby';
7+
import gs from 'glob-stream';
8+
import fastGlob from 'fast-glob';
9+
import {globby, globbySync} from './index.js';
910

11+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
1012
const BENCH_DIR = 'bench';
1113

1214
const runners = [{
1315
name: 'globby async (working directory)',
1416
run: async (patterns, callback) => {
1517
await globby(patterns);
1618
callback();
17-
}
19+
},
1820
}, {
1921
name: 'globby async (upstream/main)',
2022
run: async (patterns, callback) => {
2123
await globbyMainBranch(patterns);
2224
callback();
23-
}
25+
},
2426
}, {
2527
name: 'globby sync (working directory)',
2628
run: patterns => {
27-
globby.sync(patterns);
28-
}
29+
globbySync(patterns);
30+
},
2931
}, {
3032
name: 'globby sync (upstream/main)',
3133
run: patterns => {
3234
globbyMainBranch.sync(patterns);
33-
}
35+
},
3436
}, {
3537
name: 'glob-stream',
3638
run: (patterns, cb) => {
3739
gs(patterns).on('data', () => {}).on('end', cb);
38-
}
40+
},
3941
}, {
4042
name: 'fast-glob async',
4143
run: async (patterns, callback) => {
4244
await fastGlob(patterns);
4345
callback();
44-
}
46+
},
4547
}, {
4648
name: 'fast-glob sync',
4749
run: patterns => {
4850
fastGlob.sync(patterns);
49-
}
51+
},
5052
}];
5153
const benchs = [{
5254
name: 'negative globs (some files inside dir)',
5355
patterns: [
5456
'a/*',
55-
'!a/c*'
56-
]
57+
'!a/c*',
58+
],
5759
}, {
5860
name: 'negative globs (whole dir)',
5961
patterns: [
6062
'a/*',
61-
'!a/**'
62-
]
63+
'!a/**',
64+
],
6365
}, {
6466
name: 'multiple positive globs',
6567
patterns: [
6668
'a/*',
67-
'b/*'
68-
]
69+
'b/*',
70+
],
6971
}];
7072

7173
before(() => {
7274
process.chdir(__dirname);
7375
rimraf.sync(BENCH_DIR);
7476
fs.mkdirSync(BENCH_DIR);
7577
process.chdir(BENCH_DIR);
76-
['a', 'b']
77-
.map(directory => `${directory}/`)
78-
.forEach(directory => {
79-
fs.mkdirSync(directory);
80-
for (let i = 0; i < 500; i++) {
81-
fs.writeFileSync(directory + (i < 100 ? 'c' : 'd') + i, '');
82-
}
83-
});
78+
const directories = ['a', 'b']
79+
.map(directory => `${directory}/`);
80+
81+
for (const directory of directories) {
82+
fs.mkdirSync(directory);
83+
for (let i = 0; i < 500; i++) {
84+
fs.writeFileSync(directory + (i < 100 ? 'c' : 'd') + i, '');
85+
}
86+
}
8487
});
8588

8689
after(() => {
8790
process.chdir(__dirname);
8891
rimraf.sync(BENCH_DIR);
8992
});
9093

91-
benchs.forEach(benchmark => {
94+
for (const benchmark of benchs) {
9295
suite(benchmark.name, () => {
93-
runners.forEach(runner => bench(runner.name, runner.run.bind(null, benchmark.patterns)));
96+
for (const runner of runners) {
97+
bench(runner.name, runner.run.bind(null, benchmark.patterns));
98+
}
9499
});
95-
});
100+
}

‎gitignore.js

+20-24
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
'use strict';
2-
const {promisify} = require('util');
3-
const fs = require('fs');
4-
const path = require('path');
5-
const fastGlob = require('fast-glob');
6-
const gitIgnore = require('ignore');
7-
const slash = require('slash');
1+
import {promisify} from 'node:util';
2+
import fs from 'node:fs';
3+
import path from 'node:path';
4+
import fastGlob from 'fast-glob';
5+
import gitIgnore from 'ignore';
6+
import slash from 'slash';
87

98
const DEFAULT_IGNORE = [
109
'**/node_modules/**',
1110
'**/flow-typed/**',
1211
'**/coverage/**',
13-
'**/.git'
12+
'**/.git',
1413
];
1514

1615
const readFileP = promisify(fs.readFile);
@@ -38,7 +37,7 @@ const reduceIgnore = files => {
3837
for (const file of files) {
3938
ignores.add(parseGitIgnore(file.content, {
4039
cwd: file.cwd,
41-
fileName: file.filePath
40+
fileName: file.filePath,
4241
}));
4342
}
4443

@@ -58,9 +57,7 @@ const ensureAbsolutePathForCwd = (cwd, p) => {
5857
return path.join(cwd, p);
5958
};
6059

61-
const getIsIgnoredPredecate = (ignores, cwd) => {
62-
return p => ignores.ignores(slash(path.relative(cwd, ensureAbsolutePathForCwd(cwd, p.path || p))));
63-
};
60+
const getIsIgnoredPredicate = (ignores, cwd) => p => ignores.ignores(slash(path.relative(cwd, ensureAbsolutePathForCwd(cwd, p.path || p))));
6461

6562
const getFile = async (file, cwd) => {
6663
const filePath = path.join(cwd, file);
@@ -69,7 +66,7 @@ const getFile = async (file, cwd) => {
6966
return {
7067
cwd,
7168
filePath,
72-
content
69+
content,
7370
};
7471
};
7572

@@ -80,41 +77,40 @@ const getFileSync = (file, cwd) => {
8077
return {
8178
cwd,
8279
filePath,
83-
content
80+
content,
8481
};
8582
};
8683

8784
const normalizeOptions = ({
8885
ignore = [],
89-
cwd = slash(process.cwd())
90-
} = {}) => {
91-
return {ignore, cwd};
92-
};
86+
cwd = slash(process.cwd()),
87+
} = {}) => ({ignore, cwd});
9388

94-
module.exports = async options => {
89+
export const isGitIgnored = async options => {
9590
options = normalizeOptions(options);
9691

9792
const paths = await fastGlob('**/.gitignore', {
9893
ignore: DEFAULT_IGNORE.concat(options.ignore),
99-
cwd: options.cwd
94+
cwd: options.cwd,
10095
});
10196

10297
const files = await Promise.all(paths.map(file => getFile(file, options.cwd)));
10398
const ignores = reduceIgnore(files);
10499

105-
return getIsIgnoredPredecate(ignores, options.cwd);
100+
return getIsIgnoredPredicate(ignores, options.cwd);
106101
};
107102

108-
module.exports.sync = options => {
103+
export const isGitIgnoredSync = options => {
109104
options = normalizeOptions(options);
110105

111106
const paths = fastGlob.sync('**/.gitignore', {
112107
ignore: DEFAULT_IGNORE.concat(options.ignore),
113-
cwd: options.cwd
108+
cwd: options.cwd,
114109
});
115110

116111
const files = paths.map(file => getFileSync(file, options.cwd));
117112
const ignores = reduceIgnore(files);
118113

119-
return getIsIgnoredPredecate(ignores, options.cwd);
114+
return getIsIgnoredPredicate(ignores, options.cwd);
120115
};
116+

‎gitignore.test.js

+19-16
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,34 @@
1-
const path = require('path');
2-
const test = require('ava');
3-
const slash = require('slash');
4-
const gitignore = require('./gitignore');
1+
import path from 'node:path';
2+
import {fileURLToPath} from 'node:url';
3+
import test from 'ava';
4+
import slash from 'slash';
5+
import {isGitIgnored, isGitIgnoredSync} from './gitignore.js';
6+
7+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
58

69
test('gitignore', async t => {
710
const cwd = path.join(__dirname, 'fixtures/gitignore');
8-
const isIgnored = await gitignore({cwd});
11+
const isIgnored = await isGitIgnored({cwd});
912
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
1013
const expected = ['bar.js'];
1114
t.deepEqual(actual, expected);
1215
});
1316

1417
test('gitignore - mixed path styles', async t => {
1518
const cwd = path.join(__dirname, 'fixtures/gitignore');
16-
const isIgnored = await gitignore({cwd});
19+
const isIgnored = await isGitIgnored({cwd});
1720
t.true(isIgnored(slash(path.resolve(cwd, 'foo.js'))));
1821
});
1922

2023
test('gitignore - os paths', async t => {
2124
const cwd = path.join(__dirname, 'fixtures/gitignore');
22-
const isIgnored = await gitignore({cwd});
25+
const isIgnored = await isGitIgnored({cwd});
2326
t.true(isIgnored(path.resolve(cwd, 'foo.js')));
2427
});
2528

2629
test('gitignore - sync', t => {
2730
const cwd = path.join(__dirname, 'fixtures/gitignore');
28-
const isIgnored = gitignore.sync({cwd});
31+
const isIgnored = isGitIgnoredSync({cwd});
2932
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
3033
const expected = ['bar.js'];
3134
t.deepEqual(actual, expected);
@@ -35,7 +38,7 @@ test('ignore ignored .gitignore', async t => {
3538
const cwd = path.join(__dirname, 'fixtures/gitignore');
3639
const ignore = ['**/.gitignore'];
3740

38-
const isIgnored = await gitignore({cwd, ignore});
41+
const isIgnored = await isGitIgnored({cwd, ignore});
3942
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
4043
const expected = ['foo.js', 'bar.js'];
4144
t.deepEqual(actual, expected);
@@ -45,37 +48,37 @@ test('ignore ignored .gitignore - sync', t => {
4548
const cwd = path.join(__dirname, 'fixtures/gitignore');
4649
const ignore = ['**/.gitignore'];
4750

48-
const isIgnored = gitignore.sync({cwd, ignore});
51+
const isIgnored = isGitIgnoredSync({cwd, ignore});
4952
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
5053
const expected = ['foo.js', 'bar.js'];
5154
t.deepEqual(actual, expected);
5255
});
5356

5457
test('negative gitignore', async t => {
5558
const cwd = path.join(__dirname, 'fixtures/negative');
56-
const isIgnored = await gitignore({cwd});
59+
const isIgnored = await isGitIgnored({cwd});
5760
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
5861
const expected = ['foo.js'];
5962
t.deepEqual(actual, expected);
6063
});
6164

6265
test('negative gitignore - sync', t => {
6366
const cwd = path.join(__dirname, 'fixtures/negative');
64-
const isIgnored = gitignore.sync({cwd});
67+
const isIgnored = isGitIgnoredSync({cwd});
6568
const actual = ['foo.js', 'bar.js'].filter(file => !isIgnored(file));
6669
const expected = ['foo.js'];
6770
t.deepEqual(actual, expected);
6871
});
6972

7073
test('multiple negation', async t => {
7174
const cwd = path.join(__dirname, 'fixtures/multiple-negation');
72-
const isIgnored = await gitignore({cwd});
75+
const isIgnored = await isGitIgnored({cwd});
7376

7477
const actual = [
7578
'!!!unicorn.js',
7679
'!!unicorn.js',
7780
'!unicorn.js',
78-
'unicorn.js'
81+
'unicorn.js',
7982
].filter(file => !isIgnored(file));
8083

8184
const expected = ['!!unicorn.js', '!unicorn.js'];
@@ -84,13 +87,13 @@ test('multiple negation', async t => {
8487

8588
test('multiple negation - sync', t => {
8689
const cwd = path.join(__dirname, 'fixtures/multiple-negation');
87-
const isIgnored = gitignore.sync({cwd});
90+
const isIgnored = isGitIgnoredSync({cwd});
8891

8992
const actual = [
9093
'!!!unicorn.js',
9194
'!!unicorn.js',
9295
'!unicorn.js',
93-
'unicorn.js'
96+
'unicorn.js',
9497
].filter(file => !isIgnored(file));
9598

9699
const expected = ['!!unicorn.js', '!unicorn.js'];

‎index.d.ts

+67-75
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import {Options as FastGlobOptions, Entry as FastGlobEntry} from 'fast-glob';
22

3-
declare namespace globby {
4-
type ExpandDirectoriesOption =
5-
| boolean
6-
| readonly string[]
7-
| {files?: readonly string[]; extensions?: readonly string[]};
3+
type ExpandDirectoriesOption =
4+
| boolean
5+
| readonly string[]
6+
| {files?: readonly string[]; extensions?: readonly string[]};
87

9-
type Entry = FastGlobEntry;
8+
type GlobbyEntry = FastGlobEntry;
109

11-
interface GlobbyOptions extends FastGlobOptions {
12-
/**
10+
interface GlobbyOptions extends FastGlobOptions {
11+
/**
1312
If set to `true`, `globby` will automatically glob directories for you. If you define an `Array` it will only glob files that matches the patterns inside the `Array`. You can also define an `Object` with `files` and `extensions` like in the example below.
1413
1514
Note that if you set this option to `false`, you won't get back matched directories unless you set `onlyFiles: false`.
@@ -18,7 +17,7 @@ declare namespace globby {
1817
1918
@example
2019
```
21-
import globby = require('globby');
20+
import {globby} from 'globby';
2221
2322
(async () => {
2423
const paths = await globby('images', {
@@ -32,73 +31,69 @@ declare namespace globby {
3231
//=> ['cat.png', 'unicorn.png', 'cow.jpg', 'rainbow.jpg']
3332
})();
3433
```
35-
*/
36-
readonly expandDirectories?: ExpandDirectoriesOption;
34+
*/
35+
readonly expandDirectories?: ExpandDirectoriesOption;
3736

38-
/**
37+
/**
3938
Respect ignore patterns in `.gitignore` files that apply to the globbed files.
4039
4140
@default false
42-
*/
43-
readonly gitignore?: boolean;
44-
}
45-
46-
interface GlobTask {
47-
readonly pattern: string;
48-
readonly options: GlobbyOptions;
49-
}
41+
*/
42+
readonly gitignore?: boolean;
43+
}
5044

51-
interface GitignoreOptions {
52-
readonly cwd?: string;
53-
readonly ignore?: readonly string[];
54-
}
45+
interface GlobTask {
46+
readonly pattern: string;
47+
readonly options: GlobbyOptions;
48+
}
5549

56-
type FilterFunction = (path: string) => boolean;
50+
interface GitignoreOptions {
51+
readonly cwd?: string;
52+
readonly ignore?: readonly string[];
5753
}
5854

59-
interface Gitignore {
60-
/**
61-
@returns A filter function indicating whether a given path is ignored via a `.gitignore` file.
62-
*/
63-
sync: (options?: globby.GitignoreOptions) => globby.FilterFunction;
55+
type GlobbyFilterFunction = (path: string) => boolean;
6456

65-
/**
57+
/**
6658
`.gitignore` files matched by the ignore config are not used for the resulting filter function.
6759
6860
@returns A filter function indicating whether a given path is ignored via a `.gitignore` file.
6961
7062
@example
7163
```
72-
import {gitignore} from 'globby';
64+
import {isGitIgnored} from 'globby';
7365
7466
(async () => {
75-
const isIgnored = await gitignore();
67+
const isIgnored = await isGitIgnored();
7668
console.log(isIgnored('some/file'));
7769
})();
7870
```
79-
*/
80-
(options?: globby.GitignoreOptions): Promise<globby.FilterFunction>;
81-
}
71+
*/
72+
declare const isGitIgnored: (options?: GitignoreOptions) => Promise<GlobbyFilterFunction>;
8273

83-
declare const globby: {
84-
/**
74+
/**
75+
@returns A filter function indicating whether a given path is ignored via a `.gitignore` file.
76+
*/
77+
declare const isGitIgnoredSync: (options?: GitignoreOptions) => GlobbyFilterFunction;
78+
79+
/**
8580
Find files and directories using glob patterns.
8681
8782
Note that glob patterns can only contain forward-slashes, not backward-slashes, so if you want to construct a glob pattern from path components, you need to use `path.posix.join()` instead of `path.join()`.
8883
8984
@param patterns - See the supported [glob patterns](https://github.com/sindresorhus/globby#globbing-patterns).
9085
@param options - See the [`fast-glob` options](https://github.com/mrmlnc/fast-glob#options-3) in addition to the ones in this package.
9186
@returns The matching paths.
92-
*/
93-
sync: ((
94-
patterns: string | readonly string[],
95-
options: globby.GlobbyOptions & {objectMode: true}
96-
) => globby.Entry[]) & ((
97-
patterns: string | readonly string[],
98-
options?: globby.GlobbyOptions
99-
) => string[]);
100-
101-
/**
87+
*/
88+
declare const globbySync: ((
89+
patterns: string | readonly string[],
90+
options: GlobbyOptions & {objectMode: true}
91+
) => GlobbyEntry[]) & ((
92+
patterns: string | readonly string[],
93+
options?: GlobbyOptions
94+
) => string[]);
95+
96+
/**
10297
Find files and directories using glob patterns.
10398
10499
Note that glob patterns can only contain forward-slashes, not backward-slashes, so if you want to construct a glob pattern from path components, you need to use `path.posix.join()` instead of `path.join()`.
@@ -109,52 +104,51 @@ declare const globby: {
109104
110105
@example
111106
```
112-
import globby = require('globby');
107+
import {globbyStream} from 'globby';
113108
114109
(async () => {
115-
for await (const path of globby.stream('*.tmp')) {
110+
for await (const path of globbyStream('*.tmp')) {
116111
console.log(path);
117112
}
118113
})();
119114
```
120-
*/
121-
stream: (
122-
patterns: string | readonly string[],
123-
options?: globby.GlobbyOptions
124-
) => NodeJS.ReadableStream;
115+
*/
116+
declare const globbyStream: (
117+
patterns: string | readonly string[],
118+
options?: GlobbyOptions
119+
) => NodeJS.ReadableStream;
125120

126-
/**
121+
/**
127122
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.
128123
129124
@param patterns - See the supported [glob patterns](https://github.com/sindresorhus/globby#globbing-patterns).
130125
@param options - See the [`fast-glob` options](https://github.com/mrmlnc/fast-glob#options-3) in addition to the ones in this package.
131126
@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.
132-
*/
133-
generateGlobTasks: (
134-
patterns: string | readonly string[],
135-
options?: globby.GlobbyOptions
136-
) => globby.GlobTask[];
127+
*/
128+
declare const generateGlobTasks: (
129+
patterns: string | readonly string[],
130+
options?: GlobbyOptions
131+
) => GlobTask[];
137132

138-
/**
133+
/**
139134
Note that the options affect the results.
140135
141136
This function is backed by [`fast-glob`](https://github.com/mrmlnc/fast-glob#isdynamicpatternpattern-options).
142137
143138
@param patterns - See the supported [glob patterns](https://github.com/sindresorhus/globby#globbing-patterns).
144139
@param options - See the [`fast-glob` options](https://github.com/mrmlnc/fast-glob#options-3).
145140
@returns Whether there are any special glob characters in the `patterns`.
146-
*/
147-
hasMagic: (
148-
patterns: string | readonly string[],
149-
options?: FastGlobOptions
150-
) => boolean;
151-
152-
readonly gitignore: Gitignore;
141+
*/
142+
declare const isDynamicPattern: (
143+
patterns: string | readonly string[],
144+
options?: FastGlobOptions
145+
) => boolean;
153146

147+
declare const globby: {
154148
(
155149
patterns: string | readonly string[],
156-
options: globby.GlobbyOptions & {objectMode: true}
157-
): Promise<globby.Entry[]>;
150+
options: GlobbyOptions & {objectMode: true}
151+
): Promise<GlobbyEntry[]>;
158152

159153
/**
160154
Find files and directories using glob patterns.
@@ -167,7 +161,7 @@ declare const globby: {
167161
168162
@example
169163
```
170-
import globby = require('globby');
164+
import {globby} from 'globby';
171165
172166
(async () => {
173167
const paths = await globby(['*', '!cake']);
@@ -179,8 +173,6 @@ declare const globby: {
179173
*/
180174
(
181175
patterns: string | readonly string[],
182-
options?: globby.GlobbyOptions
176+
options?: GlobbyOptions
183177
): Promise<string[]>;
184178
};
185-
186-
export = globby;

‎index.js

+28-33
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
'use strict';
2-
const fs = require('fs');
3-
const arrayUnion = require('array-union');
4-
const merge2 = require('merge2');
5-
const fastGlob = require('fast-glob');
6-
const dirGlob = require('dir-glob');
7-
const gitignore = require('./gitignore');
8-
const {FilterStream, UniqueStream} = require('./stream-utils');
1+
import fs from 'node:fs';
2+
import arrayUnion from 'array-union';
3+
import merge2 from 'merge2';
4+
import fastGlob from 'fast-glob';
5+
import dirGlob from 'dir-glob';
6+
import {isGitIgnored, isGitIgnoredSync} from './gitignore.js';
7+
import {FilterStream, UniqueStream} from './stream-utils.js';
98

109
const DEFAULT_FILTER = () => false;
1110

@@ -36,8 +35,8 @@ const checkCwdOption = (options = {}) => {
3635

3736
const getPathString = p => p.stats instanceof fs.Stats ? p.path : p;
3837

39-
const generateGlobTasks = (patterns, taskOptions) => {
40-
patterns = arrayUnion([].concat(patterns));
38+
export const generateGlobTasks = (patterns, taskOptions) => {
39+
patterns = arrayUnion([patterns].flat());
4140
assertPatternsInput(patterns);
4241
checkCwdOption(taskOptions);
4342

@@ -46,7 +45,7 @@ const generateGlobTasks = (patterns, taskOptions) => {
4645
taskOptions = {
4746
ignore: [],
4847
expandDirectories: true,
49-
...taskOptions
48+
...taskOptions,
5049
};
5150

5251
for (const [index, pattern] of patterns.entries()) {
@@ -61,7 +60,7 @@ const generateGlobTasks = (patterns, taskOptions) => {
6160

6261
const options = {
6362
...taskOptions,
64-
ignore: taskOptions.ignore.concat(ignore)
63+
ignore: [...taskOptions.ignore, ...ignore],
6564
};
6665

6766
globTasks.push({pattern, options});
@@ -79,12 +78,12 @@ const globDirs = (task, fn) => {
7978
if (Array.isArray(task.options.expandDirectories)) {
8079
options = {
8180
...options,
82-
files: task.options.expandDirectories
81+
files: task.options.expandDirectories,
8382
};
8483
} else if (typeof task.options.expandDirectories === 'object') {
8584
options = {
8685
...options,
87-
...task.options.expandDirectories
86+
...task.options.expandDirectories,
8887
};
8988
}
9089

@@ -93,11 +92,9 @@ const globDirs = (task, fn) => {
9392

9493
const getPattern = (task, fn) => task.options.expandDirectories ? globDirs(task, fn) : [task.pattern];
9594

96-
const getFilterSync = options => {
97-
return options && options.gitignore ?
98-
gitignore.sync({cwd: options.cwd, ignore: options.ignore}) :
99-
DEFAULT_FILTER;
100-
};
95+
const getFilterSync = options => options && options.gitignore
96+
? isGitIgnoredSync({cwd: options.cwd, ignore: options.ignore})
97+
: DEFAULT_FILTER;
10198

10299
const globToTask = task => glob => {
103100
const {options} = task;
@@ -107,18 +104,16 @@ const globToTask = task => glob => {
107104

108105
return {
109106
pattern: glob,
110-
options
107+
options,
111108
};
112109
};
113110

114-
module.exports = async (patterns, options) => {
111+
export const globby = async (patterns, options) => {
115112
const globTasks = generateGlobTasks(patterns, options);
116113

117-
const getFilter = async () => {
118-
return options && options.gitignore ?
119-
gitignore({cwd: options.cwd, ignore: options.ignore}) :
120-
DEFAULT_FILTER;
121-
};
114+
const getFilter = async () => options && options.gitignore
115+
? isGitIgnored({cwd: options.cwd, ignore: options.ignore})
116+
: DEFAULT_FILTER;
122117

123118
const getTasks = async () => {
124119
const tasks = await Promise.all(globTasks.map(async task => {
@@ -135,7 +130,7 @@ module.exports = async (patterns, options) => {
135130
return arrayUnion(...paths).filter(path_ => !filter(getPathString(path_)));
136131
};
137132

138-
module.exports.sync = (patterns, options) => {
133+
export const globbySync = (patterns, options) => {
139134
const globTasks = generateGlobTasks(patterns, options);
140135

141136
const tasks = [];
@@ -154,7 +149,7 @@ module.exports.sync = (patterns, options) => {
154149
return matches.filter(path_ => !filter(path_));
155150
};
156151

157-
module.exports.stream = (patterns, options) => {
152+
export const globbyStream = (patterns, options) => {
158153
const globTasks = generateGlobTasks(patterns, options);
159154

160155
const tasks = [];
@@ -172,10 +167,10 @@ module.exports.stream = (patterns, options) => {
172167
.pipe(uniqueStream);
173168
};
174169

175-
module.exports.generateGlobTasks = generateGlobTasks;
176-
177-
module.exports.hasMagic = (patterns, options) => []
178-
.concat(patterns)
170+
export const isDynamicPattern = (patterns, options) => [patterns].flat()
179171
.some(pattern => fastGlob.isDynamicPattern(pattern, options));
180172

181-
module.exports.gitignore = gitignore;
173+
export {
174+
isGitIgnored,
175+
isGitIgnoredSync,
176+
};

‎index.test-d.ts

+53-47
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,40 @@
1+
import {dirname} from 'node:path';
2+
import {fileURLToPath} from 'node:url';
13
import {expectType} from 'tsd';
2-
import globby = require('.');
34
import {
45
GlobTask,
5-
FilterFunction,
6-
sync as globbySync,
7-
stream as globbyStream,
6+
GlobbyEntry,
7+
GlobbyFilterFunction,
8+
globby,
9+
globbySync,
10+
globbyStream,
811
generateGlobTasks,
9-
hasMagic,
10-
gitignore
11-
} from '.';
12+
isDynamicPattern,
13+
isGitIgnored,
14+
isGitIgnoredSync,
15+
} from './index.js';
16+
17+
const __dirname = dirname(fileURLToPath(import.meta.url));
1218

1319
// Globby
1420
expectType<Promise<string[]>>(globby('*.tmp'));
1521
expectType<Promise<string[]>>(globby(['a.tmp', '*.tmp', '!{c,d,e}.tmp']));
1622

1723
expectType<Promise<string[]>>(globby('*.tmp', {expandDirectories: false}));
1824
expectType<Promise<string[]>>(
19-
globby('*.tmp', {expandDirectories: ['a*', 'b*']})
25+
globby('*.tmp', {expandDirectories: ['a*', 'b*']}),
2026
);
2127
expectType<Promise<string[]>>(
2228
globby('*.tmp', {
2329
expandDirectories: {
2430
files: ['a', 'b'],
25-
extensions: ['tmp']
26-
}
27-
})
31+
extensions: ['tmp'],
32+
},
33+
}),
2834
);
2935
expectType<Promise<string[]>>(globby('*.tmp', {gitignore: true}));
3036
expectType<Promise<string[]>>(globby('*.tmp', {ignore: ['**/b.tmp']}));
31-
expectType<Promise<globby.Entry[]>>(globby('*.tmp', {objectMode: true}));
37+
expectType<Promise<GlobbyEntry[]>>(globby('*.tmp', {objectMode: true}));
3238

3339
// Globby (sync)
3440
expectType<string[]>(globbySync('*.tmp'));
@@ -40,13 +46,13 @@ expectType<string[]>(
4046
globbySync('*.tmp', {
4147
expandDirectories: {
4248
files: ['a', 'b'],
43-
extensions: ['tmp']
44-
}
45-
})
49+
extensions: ['tmp'],
50+
},
51+
}),
4652
);
4753
expectType<string[]>(globbySync('*.tmp', {gitignore: true}));
4854
expectType<string[]>(globbySync('*.tmp', {ignore: ['**/b.tmp']}));
49-
expectType<globby.Entry[]>(globbySync('*.tmp', {objectMode: true}));
55+
expectType<GlobbyEntry[]>(globbySync('*.tmp', {objectMode: true}));
5056

5157
// Globby (stream)
5258
expectType<NodeJS.ReadableStream>(globbyStream('*.tmp'));
@@ -58,9 +64,9 @@ expectType<NodeJS.ReadableStream>(
5864
globbyStream('*.tmp', {
5965
expandDirectories: {
6066
files: ['a', 'b'],
61-
extensions: ['tmp']
62-
}
63-
})
67+
extensions: ['tmp'],
68+
},
69+
}),
6470
);
6571
expectType<NodeJS.ReadableStream>(globbyStream('*.tmp', {gitignore: true}));
6672
expectType<NodeJS.ReadableStream>(globbyStream('*.tmp', {ignore: ['**/b.tmp']}));
@@ -82,46 +88,46 @@ expectType<GlobTask[]>(generateGlobTasks(['a.tmp', '*.tmp', '!{c,d,e}.tmp']));
8288

8389
expectType<GlobTask[]>(generateGlobTasks('*.tmp', {expandDirectories: false}));
8490
expectType<GlobTask[]>(
85-
generateGlobTasks('*.tmp', {expandDirectories: ['a*', 'b*']})
91+
generateGlobTasks('*.tmp', {expandDirectories: ['a*', 'b*']}),
8692
);
8793
expectType<GlobTask[]>(
8894
generateGlobTasks('*.tmp', {
8995
expandDirectories: {
9096
files: ['a', 'b'],
91-
extensions: ['tmp']
92-
}
93-
})
97+
extensions: ['tmp'],
98+
},
99+
}),
94100
);
95101
expectType<GlobTask[]>(generateGlobTasks('*.tmp', {gitignore: true}));
96102
expectType<GlobTask[]>(generateGlobTasks('*.tmp', {ignore: ['**/b.tmp']}));
97103

98-
// HasMagic
99-
expectType<boolean>(hasMagic('**'));
100-
expectType<boolean>(hasMagic(['**', 'path1', 'path2']));
101-
expectType<boolean>(hasMagic(['**', 'path1', 'path2'], {extglob: false}));
104+
// IsDynamicPattern
105+
expectType<boolean>(isDynamicPattern('**'));
106+
expectType<boolean>(isDynamicPattern(['**', 'path1', 'path2']));
107+
expectType<boolean>(isDynamicPattern(['**', 'path1', 'path2'], {extglob: false}));
102108

103-
// Gitignore
104-
expectType<Promise<FilterFunction>>(gitignore());
105-
expectType<Promise<FilterFunction>>(
106-
gitignore({
107-
cwd: __dirname
108-
})
109+
// IsGitIgnored
110+
expectType<Promise<GlobbyFilterFunction>>(isGitIgnored());
111+
expectType<Promise<GlobbyFilterFunction>>(
112+
isGitIgnored({
113+
cwd: __dirname,
114+
}),
109115
);
110-
expectType<Promise<FilterFunction>>(
111-
gitignore({
112-
ignore: ['**/b.tmp']
113-
})
116+
expectType<Promise<GlobbyFilterFunction>>(
117+
isGitIgnored({
118+
ignore: ['**/b.tmp'],
119+
}),
114120
);
115121

116-
// Gitignore (sync)
117-
expectType<FilterFunction>(gitignore.sync());
118-
expectType<FilterFunction>(
119-
gitignore.sync({
120-
cwd: __dirname
121-
})
122+
// IsGitIgnoredSync
123+
expectType<GlobbyFilterFunction>(isGitIgnoredSync());
124+
expectType<GlobbyFilterFunction>(
125+
isGitIgnoredSync({
126+
cwd: __dirname,
127+
}),
122128
);
123-
expectType<FilterFunction>(
124-
gitignore.sync({
125-
ignore: ['**/b.tmp']
126-
})
129+
expectType<GlobbyFilterFunction>(
130+
isGitIgnoredSync({
131+
ignore: ['**/b.tmp'],
132+
}),
127133
);

‎package.json

+19-10
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
"url": "https://sindresorhus.com"
1212
},
1313
"engines": {
14-
"node": ">=10"
14+
"node": ">=12.20"
1515
},
16+
"type": "module",
17+
"exports": "./index.js",
1618
"scripts": {
1719
"bench": "npm update glob-stream fast-glob && matcha bench.js",
1820
"test": "xo && ava && tsd"
@@ -57,22 +59,29 @@
5759
"git"
5860
],
5961
"dependencies": {
60-
"array-union": "^2.1.0",
62+
"array-union": "^3.0.1",
6163
"dir-glob": "^3.0.1",
62-
"fast-glob": "^3.1.1",
63-
"ignore": "^5.1.4",
64-
"merge2": "^1.3.0",
65-
"slash": "^3.0.0"
64+
"fast-glob": "^3.2.7",
65+
"ignore": "^5.1.8",
66+
"merge2": "^1.4.1",
67+
"slash": "^4.0.0"
6668
},
6769
"devDependencies": {
68-
"ava": "^3.13.0",
69-
"get-stream": "^6.0.0",
70+
"@types/node": "^16.3.3",
71+
"ava": "^3.15.0",
72+
"get-stream": "^6.0.1",
7073
"glob-stream": "^6.1.0",
7174
"globby": "sindresorhus/globby#main",
7275
"matcha": "^0.7.0",
7376
"rimraf": "^3.0.2",
74-
"tsd": "^0.13.1",
75-
"xo": "^0.33.1"
77+
"typescript": "^4.3.5",
78+
"tsd": "^0.17.0",
79+
"xo": "^0.42.0"
80+
},
81+
"tsd": {
82+
"compilerOptions": {
83+
"module": "es2020"
84+
}
7685
},
7786
"xo": {
7887
"ignores": [

‎readme.md

+13-13
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ $ npm install globby
2727
```
2828

2929
```js
30-
const globby = require('globby');
30+
import {globby} from 'globby';
3131

3232
(async () => {
3333
const paths = await globby(['*', '!cake']);
@@ -65,7 +65,7 @@ Default: `true`
6565
If set to `true`, `globby` will automatically glob directories for you. If you define an `Array` it will only glob files that matches the patterns inside the `Array`. You can also define an `object` with `files` and `extensions` like below:
6666

6767
```js
68-
const globby = require('globby');
68+
import {globby} from 'globby';
6969

7070
(async () => {
7171
const paths = await globby('images', {
@@ -89,60 +89,60 @@ Default: `false`
8989

9090
Respect ignore patterns in `.gitignore` files that apply to the globbed files.
9191

92-
### globby.sync(patterns, options?)
92+
### globbySync(patterns, options?)
9393

9494
Returns `string[]` of matching paths.
9595

96-
### globby.stream(patterns, options?)
96+
### globbyStream(patterns, options?)
9797

9898
Returns a [`stream.Readable`](https://nodejs.org/api/stream.html#stream_readable_streams) of matching paths.
9999

100100
Since Node.js 10, [readable streams are iterable](https://nodejs.org/api/stream.html#stream_readable_symbol_asynciterator), so you can loop over glob matches in a [`for await...of` loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of) like this:
101101

102102
```js
103-
const globby = require('globby');
103+
import {globbyStream} from 'globby';
104104

105105
(async () => {
106-
for await (const path of globby.stream('*.tmp')) {
106+
for await (const path of globbyStream('*.tmp')) {
107107
console.log(path);
108108
}
109109
})();
110110
```
111111

112-
### globby.generateGlobTasks(patterns, options?)
112+
### generateGlobTasks(patterns, options?)
113113

114114
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.
115115

116116
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.
117117

118-
### globby.hasMagic(patterns, options?)
118+
### isDynamicPattern(patterns, options?)
119119

120120
Returns a `boolean` of whether there are any special glob characters in the `patterns`.
121121

122122
Note that the options affect the results.
123123

124124
This function is backed by [`fast-glob`](https://github.com/mrmlnc/fast-glob#isdynamicpatternpattern-options).
125125

126-
### globby.gitignore(options?)
126+
### isGitIgnored(options?)
127127

128128
Returns a `Promise<(path: string) => boolean>` indicating whether a given path is ignored via a `.gitignore` file.
129129

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

132132
```js
133-
const {gitignore} = require('globby');
133+
import {isGitIgnored} from 'globby';
134134

135135
(async () => {
136-
const isIgnored = await gitignore();
136+
const isIgnored = await isGitIgnored();
137137
console.log(isIgnored('some/file'));
138138
})();
139139
```
140140

141-
### globby.gitignore.sync(options?)
141+
### isGitIgnoredSync(options?)
142142

143143
Returns a `(path: string) => boolean` indicating whether a given path is ignored via a `.gitignore` file.
144144

145-
Takes the same options as `globby.gitignore`.
145+
Takes the same options as `isGitIgnored`.
146146

147147
## Globbing patterns
148148

‎stream-utils.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
'use strict';
2-
const {Transform} = require('stream');
1+
import {Transform} from 'node:stream';
32

43
class ObjectTransform extends Transform {
54
constructor() {
65
super({
7-
objectMode: true
6+
objectMode: true,
87
});
98
}
109
}
@@ -40,7 +39,7 @@ class UniqueStream extends ObjectTransform {
4039
}
4140
}
4241

43-
module.exports = {
42+
export {
4443
FilterStream,
45-
UniqueStream
44+
UniqueStream,
4645
};

‎test.js

+85-77
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.