2021-09-17 00:26:18 -04:00
|
|
|
/**
|
|
|
|
|
* @file Retrieve the first available glob library.
|
|
|
|
|
*
|
|
|
|
|
* Note that options vary between libraries.
|
|
|
|
|
*
|
|
|
|
|
* Candidates:
|
2022-02-15 09:16:03 -05:00
|
|
|
*
|
2022-10-13 14:47:11 -04:00
|
|
|
* - {@link https://npmjs.com/package/tiny-glob tiny-glob} [1][5][6]
|
|
|
|
|
* - {@link https://npmjs.com/package/globby globby} [2][5]
|
|
|
|
|
* - {@link https://npmjs.com/package/fast-glob fast-glob} [3]
|
|
|
|
|
* - {@link https://npmjs.com/package/glob glob} [1][4][5]
|
|
|
|
|
*
|
|
|
|
|
* Notes:
|
|
|
|
|
*
|
|
|
|
|
* - [1] The library's function accepts only a single pattern.
|
|
|
|
|
* - [2] The library's function accepts only an array of patterns.
|
|
|
|
|
* - [3] The library's function accepts either a single pattern
|
|
|
|
|
* or an array of patterns.
|
|
|
|
|
* - [4] The library's function does not return a Promise but will be
|
|
|
|
|
* wrapped in a function that does return a Promise.
|
|
|
|
|
* - [5] The library's function will be wrapped in a function that
|
|
|
|
|
* supports a single pattern and an array of patterns.
|
|
|
|
|
* - [6] The library's function returns files and directories but will be
|
|
|
|
|
* preconfigured to return only files.
|
2021-09-17 00:26:18 -04:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { promisify } from 'node:util';
|
|
|
|
|
|
2022-10-13 14:47:11 -04:00
|
|
|
/**
|
|
|
|
|
* @callback GlobFn
|
|
|
|
|
*
|
|
|
|
|
* @param {string|string[]} patterns - A string pattern
|
|
|
|
|
* or an array of string patterns.
|
|
|
|
|
* @param {object} options
|
|
|
|
|
*
|
|
|
|
|
* @returns {Promise<string[]>}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @typedef {object} GlobOptions
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @type {GlobFn|undefined} The discovered glob function.
|
|
|
|
|
*/
|
|
|
|
|
let glob;
|
|
|
|
|
|
2021-09-21 16:54:54 -04:00
|
|
|
/**
|
|
|
|
|
* @type {string[]} A list of packages to attempt import.
|
|
|
|
|
*/
|
2021-09-21 15:59:48 -04:00
|
|
|
const candidates = [
|
2021-09-17 00:26:18 -04:00
|
|
|
'tiny-glob',
|
|
|
|
|
'globby',
|
|
|
|
|
'fast-glob',
|
|
|
|
|
'glob',
|
|
|
|
|
];
|
|
|
|
|
|
2022-02-08 15:18:18 -05:00
|
|
|
try {
|
|
|
|
|
glob = await importGlob();
|
|
|
|
|
} catch (err) {
|
|
|
|
|
// do nothing
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-13 14:47:11 -04:00
|
|
|
/**
|
|
|
|
|
* @type {boolean} Whether a glob function was discovered (TRUE) or not (FALSE).
|
|
|
|
|
*/
|
2022-10-13 14:42:22 -04:00
|
|
|
const supportsGlob = (typeof glob === 'function');
|
2021-09-17 00:26:18 -04:00
|
|
|
|
2021-09-21 16:54:54 -04:00
|
|
|
/**
|
|
|
|
|
* Imports the first available glob function.
|
|
|
|
|
*
|
|
|
|
|
* @throws {TypeError} If no glob library was found.
|
2022-10-13 14:47:11 -04:00
|
|
|
*
|
|
|
|
|
* @returns {GlobFn}
|
2021-09-21 16:54:54 -04:00
|
|
|
*/
|
|
|
|
|
async function importGlob() {
|
|
|
|
|
for (let name of candidates) {
|
|
|
|
|
try {
|
2022-10-13 14:47:11 -04:00
|
|
|
let globModule = await import(name);
|
2021-09-17 00:26:18 -04:00
|
|
|
|
2022-10-13 14:47:11 -04:00
|
|
|
if (typeof globModule.default !== 'function') {
|
2021-09-21 16:54:54 -04:00
|
|
|
throw new TypeError(`Expected ${name} to be a function`);
|
|
|
|
|
}
|
2021-09-21 15:59:48 -04:00
|
|
|
|
2021-09-21 16:54:54 -04:00
|
|
|
/**
|
|
|
|
|
* Wrap the function to ensure
|
|
|
|
|
* a common pattern.
|
|
|
|
|
*/
|
|
|
|
|
switch (name) {
|
|
|
|
|
case 'tiny-glob':
|
2022-10-13 14:47:11 -04:00
|
|
|
/** [1][5] */
|
|
|
|
|
return createArrayableGlob(
|
|
|
|
|
/** [6] */
|
|
|
|
|
createPresetGlob(globModule.default, {
|
|
|
|
|
filesOnly: true
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
case 'globby':
|
|
|
|
|
/** [2][5] - If `patterns` is a string, wraps into an array. */
|
|
|
|
|
return (patterns, options) => globModule.default([].concat(patterns), options);
|
2021-09-21 16:54:54 -04:00
|
|
|
|
|
|
|
|
case 'glob':
|
2022-10-13 14:47:11 -04:00
|
|
|
/** [1][5] */
|
|
|
|
|
return createArrayableGlob(
|
|
|
|
|
/** [4] */
|
|
|
|
|
promisify(globModule.default)
|
|
|
|
|
);
|
2021-09-17 00:26:18 -04:00
|
|
|
|
2021-09-21 16:54:54 -04:00
|
|
|
default:
|
2022-10-13 14:47:11 -04:00
|
|
|
return globModule.default;
|
2021-09-21 16:54:54 -04:00
|
|
|
}
|
|
|
|
|
} catch (err) {
|
|
|
|
|
// swallow this error; skip to the next candidate.
|
|
|
|
|
}
|
2021-09-17 00:26:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new TypeError(
|
2021-12-03 15:10:21 -05:00
|
|
|
`No glob library was found, expected one of: ${candidates.join(', ')}`
|
2021-09-17 00:26:18 -04:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a wrapper function for the glob function
|
|
|
|
|
* to provide support for arrays of patterns.
|
|
|
|
|
*
|
2022-10-13 14:47:11 -04:00
|
|
|
* @param {function} globFn - The glob function.
|
|
|
|
|
*
|
|
|
|
|
* @returns {GlobFn}
|
2021-09-17 00:26:18 -04:00
|
|
|
*/
|
2022-10-13 14:47:11 -04:00
|
|
|
function createArrayableGlob(globFn) {
|
2021-09-17 00:26:18 -04:00
|
|
|
return (patterns, options) => {
|
2022-10-13 14:47:11 -04:00
|
|
|
/** [2] If `patterns` is a string, wraps into an array. */
|
|
|
|
|
patterns = [].concat(patterns);
|
|
|
|
|
|
|
|
|
|
const globs = patterns.map((pattern) => globFn(pattern, options));
|
2021-09-17 00:26:18 -04:00
|
|
|
|
|
|
|
|
return Promise.all(globs).then((files) => {
|
|
|
|
|
return [].concat.apply([], files);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
}
|
2022-10-13 14:42:22 -04:00
|
|
|
|
2022-10-13 14:47:11 -04:00
|
|
|
/**
|
|
|
|
|
* Creates a wrapper function for the glob function
|
|
|
|
|
* to define new default options.
|
|
|
|
|
*
|
|
|
|
|
* @param {function} globFn - The glob function.
|
|
|
|
|
* @param {GlobOptions} presets - The glob function options to preset.
|
|
|
|
|
*
|
|
|
|
|
* @returns {GlobFn}
|
|
|
|
|
*/
|
|
|
|
|
function createPresetGlob(globFn, presets) {
|
|
|
|
|
return (patterns, options) => globFn(patterns, Object.assign({}, presets, options));
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-13 14:42:22 -04:00
|
|
|
export default glob;
|
|
|
|
|
|
|
|
|
|
export {
|
|
|
|
|
glob,
|
|
|
|
|
supportsGlob,
|
|
|
|
|
};
|