1
0
mirror of https://github.com/locomotivemtl/locomotive-boilerplate.git synced 2026-01-15 00:55:08 +08:00

Fix glob.js and improve documentation

Documented API inconsistencies between supported glob libraries (expected/supported parameters and return types).

Fixed API inconsistencies between 'tiny-glob', 'globby', and 'glob', to match 'fast-glob'.

Fixed broken support for preset options for 'tiny-glob'.
This commit is contained in:
Chauncey McAskill
2022-10-13 14:47:11 -04:00
parent 89bb00790f
commit 1ee315663e

View File

@@ -5,14 +5,46 @@
*
* Candidates:
*
* - {@link https://npmjs.com/package/tiny-glob tiny-glob}
* - {@link https://npmjs.com/package/globby globby}
* - {@link https://npmjs.com/package/fast-glob fast-glob}
* - {@link https://npmjs.com/package/glob glob}
* - {@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.
*/
import { promisify } from 'node:util';
/**
* @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;
/**
* @type {string[]} A list of packages to attempt import.
*/
@@ -23,30 +55,30 @@ const candidates = [
'glob',
];
let glob;
try {
glob = await importGlob();
} catch (err) {
// do nothing
}
/**
* @type {boolean} Whether a glob function was discovered (TRUE) or not (FALSE).
*/
const supportsGlob = (typeof glob === 'function');
/**
* Imports the first available glob function.
*
* @throws {TypeError} If no glob library was found.
* @return {function}
*
* @returns {GlobFn}
*/
async function importGlob() {
let glob, module;
for (let name of candidates) {
try {
module = await import(name);
let globModule = await import(name);
if (typeof module.default !== 'function') {
if (typeof globModule.default !== 'function') {
throw new TypeError(`Expected ${name} to be a function`);
}
@@ -56,15 +88,27 @@ async function importGlob() {
*/
switch (name) {
case 'tiny-glob':
return createArrayableGlob(module.default, {
/** [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);
case 'glob':
return promisify(module.default);
/** [1][5] */
return createArrayableGlob(
/** [4] */
promisify(globModule.default)
);
default:
return module.default;
return globModule.default;
}
} catch (err) {
// swallow this error; skip to the next candidate.
@@ -80,13 +124,16 @@ async function importGlob() {
* Creates a wrapper function for the glob function
* to provide support for arrays of patterns.
*
* @param {function} glob - The glob function.
* @param {object} options - The glob options.
* @return {function}
* @param {function} globFn - The glob function.
*
* @returns {GlobFn}
*/
function createArrayableGlob(glob, options) {
function createArrayableGlob(globFn) {
return (patterns, options) => {
const globs = patterns.map((pattern) => glob(pattern, options));
/** [2] If `patterns` is a string, wraps into an array. */
patterns = [].concat(patterns);
const globs = patterns.map((pattern) => globFn(pattern, options));
return Promise.all(globs).then((files) => {
return [].concat.apply([], files);
@@ -94,6 +141,19 @@ function createArrayableGlob(glob, options) {
};
}
/**
* 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));
}
export default glob;
export {